library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6      ✔ purrr   0.3.5 
## ✔ tibble  3.1.8      ✔ dplyr   1.0.10
## ✔ tidyr   1.2.1      ✔ stringr 1.4.1 
## ✔ readr   2.1.3      ✔ forcats 0.5.2 
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(MSstatsPTM)
library(lme4)
## Loading required package: Matrix
## Warning: package 'Matrix' was built under R version 4.2.2
## 
## Attaching package: 'Matrix'
## 
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
library(msqrob2)
## Loading required package: QFeatures
## Loading required package: MultiAssayExperiment
## Loading required package: SummarizedExperiment
## Loading required package: MatrixGenerics
## Loading required package: matrixStats
## 
## Attaching package: 'matrixStats'
## 
## The following object is masked from 'package:dplyr':
## 
##     count
## 
## 
## Attaching package: 'MatrixGenerics'
## 
## The following objects are masked from 'package:matrixStats':
## 
##     colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse,
##     colCounts, colCummaxs, colCummins, colCumprods, colCumsums,
##     colDiffs, colIQRDiffs, colIQRs, colLogSumExps, colMadDiffs,
##     colMads, colMaxs, colMeans2, colMedians, colMins, colOrderStats,
##     colProds, colQuantiles, colRanges, colRanks, colSdDiffs, colSds,
##     colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads,
##     colWeightedMeans, colWeightedMedians, colWeightedSds,
##     colWeightedVars, rowAlls, rowAnyNAs, rowAnys, rowAvgsPerColSet,
##     rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods,
##     rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps,
##     rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians, rowMins,
##     rowOrderStats, rowProds, rowQuantiles, rowRanges, rowRanks,
##     rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars,
##     rowWeightedMads, rowWeightedMeans, rowWeightedMedians,
##     rowWeightedSds, rowWeightedVars
## 
## Loading required package: GenomicRanges
## Loading required package: stats4
## Loading required package: BiocGenerics
## 
## Attaching package: 'BiocGenerics'
## 
## The following objects are masked from 'package:dplyr':
## 
##     combine, intersect, setdiff, union
## 
## The following objects are masked from 'package:stats':
## 
##     IQR, mad, sd, var, xtabs
## 
## The following objects are masked from 'package:base':
## 
##     anyDuplicated, append, as.data.frame, basename, cbind, colnames,
##     dirname, do.call, duplicated, eval, evalq, Filter, Find, get, grep,
##     grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget,
##     order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank,
##     rbind, Reduce, rownames, sapply, setdiff, sort, table, tapply,
##     union, unique, unsplit, which.max, which.min
## 
## Loading required package: S4Vectors
## 
## Attaching package: 'S4Vectors'
## 
## The following objects are masked from 'package:Matrix':
## 
##     expand, unname
## 
## The following objects are masked from 'package:dplyr':
## 
##     first, rename
## 
## The following object is masked from 'package:tidyr':
## 
##     expand
## 
## The following objects are masked from 'package:base':
## 
##     expand.grid, I, unname
## 
## Loading required package: IRanges
## 
## Attaching package: 'IRanges'
## 
## The following objects are masked from 'package:dplyr':
## 
##     collapse, desc, slice
## 
## The following object is masked from 'package:purrr':
## 
##     reduce
## 
## The following object is masked from 'package:grDevices':
## 
##     windows
## 
## Loading required package: GenomeInfoDb
## Loading required package: Biobase
## Welcome to Bioconductor
## 
##     Vignettes contain introductory material; view with
##     'browseVignettes()'. To cite Bioconductor, see
##     'citation("Biobase")', and for packages 'citation("pkgname")'.
## 
## 
## Attaching package: 'Biobase'
## 
## The following object is masked from 'package:MatrixGenerics':
## 
##     rowMedians
## 
## The following objects are masked from 'package:matrixStats':
## 
##     anyMissing, rowMedians
## 
## 
## Attaching package: 'QFeatures'
## 
## The following object is masked from 'package:MultiAssayExperiment':
## 
##     longFormat
## 
## The following object is masked from 'package:base':
## 
##     sweep
library(data.table)
## 
## Attaching package: 'data.table'
## 
## The following object is masked from 'package:SummarizedExperiment':
## 
##     shift
## 
## The following object is masked from 'package:GenomicRanges':
## 
##     shift
## 
## The following object is masked from 'package:IRanges':
## 
##     shift
## 
## The following objects are masked from 'package:S4Vectors':
## 
##     first, second
## 
## The following objects are masked from 'package:dplyr':
## 
##     between, first, last
## 
## The following object is masked from 'package:purrr':
## 
##     transpose

Load in all data

directory = "C:/Users/Nina/OneDrive - UGent/Documenten/Doctoraat/msqrobPTM paper/biological ubiquitin dataset/"
#MSStats data
load(paste0(directory, "MSstatsSummarizedData.RData"))
load(paste0(directory, "MSstatsModel.rda"))
#Msqrob
load("pe_ubiquitin_msqrob.rda")

1 MSstats

estimated ptm abundance ->fixef(model_ptm\(Model.Details\)PTM[[100]]) protein abundance (for protein i) -> summarized_ptm\(PROTEIN\)ProteinLevelData %>% filter(Protein == i) %>% pull(LogIntensities) ptm abundance (for ptm i) -> summarized_ptm\(PTM\)ProteinLevelData %>% filter(Protein == i) %>% pull(LogIntensities) normalised ptm abundance -> model_ptm\(Model.Details\)PTM[[100]] - model_ptm\(Model.Details\)PROTEIN[[100]]

At the moment, only in the GitHub version, a detailed model gets outputted with info on the estimates on everything, so I used that here

originalRUN <- c("CCCP-B1T1", "CCCP-B1T2", "CCCP-B2T1", "CCCP-B2T2", "Combo-B1T1", 
                 "Combo-B1T2", "Combo-B2T1", "Combo-B2T2", "Ctrl-B1T1", "Ctrl-B1T2",   
                 "Ctrl-B2T1", "Ctrl-B2T2", "USP30_OE-B1T1", "USP30_OE-B1T2", 
                 "USP30_OE-B2T1", "USP30_OE-B2T2")
GROUP <- sapply(strsplit(originalRUN, "-"), function(x) x[1])
## Plot fourty ptm's from Combo vs Ctrl
ptm_list1 <- model_ptm$ADJUSTED.Model %>% filter(Label == "Combo vs Ctrl") %>% filter(adj.pvalue <= 0.05) %>% head(40) %>% pull(Protein)
all_ptms <- model_ptm$PTM.Model %>% pull(Protein) %>% unique()
all_proteins <- model_ptm$PROTEIN.Model %>% pull(Protein) %>% unique()
adjusted_ptms <- model_ptm$ADJUSTED.Model %>% pull(Protein) %>% unique()
plots <- c()
for (i in ptm_list1){
  print(i)
  prot <- strsplit(i, "_")[[1]][1]
  index <- which(all_ptms == i)
  index_prot <- which(all_proteins == prot)
  index_adjusted <- which(adjusted_ptms == i)
#Protein abundance
protein <- tibble(originalRUN, GROUP)
protein$FeatureType <- "Protein"
protein$Protein <- prot
tmp <- summarized_ptm$PROTEIN$ProteinLevelData %>% filter(Protein == prot) %>%
  select(c(LogIntensities, originalRUN))
missing_runs <- setdiff(originalRUN, tmp$originalRUN)
tmp2 <- tibble(originalRUN = missing_runs, LogIntensities = NA)
tmp3 <- rbind(tmp, tmp2) %>% arrange(originalRUN) %>% select(LogIntensities)
protein <- cbind(protein, tmp3)

#PTM abundance
ptm_df <- summarized_ptm$PTM$ProteinLevelData %>% filter(Protein == i)
ptm_df$Abundance <- ptm_df$LogIntensities
ptm_df$FeatureType <- "PTM"
ptm_df <- ptm_df %>% select(c("Protein", "LogIntensities", "originalRUN", 
                                "GROUP", "FeatureType"))

#PTM estimated (maar nog niet adjusted)
Protein <- rep(i, length(originalRUN))
ptm_estimate <- tibble(Protein)
ptm_estimate$originalRUN <- originalRUN
ptm_estimate$GROUP <- GROUP
ptm_estimate$FeatureType <- "PTM_estimated"
ptm_estimate$LogIntensities <- NA

#Check that model estimates are definitely from that PTM
if (class(model_ptm$Model.Details$PTM[[index]]) == "lm"){print(i)
  }else{
print(all(
  summarized_ptm$PTM$ProteinLevelData %>% filter(Protein == i) %>% pull(LogIntensities) ==
    getME(model_ptm$Model.Details$PTM[[index]], "y")
))}

if (class(model_ptm$Model.Details$PTM[[index]]) == "lm"){
fixeffects <- model_ptm$Model.Details$PTM[[index]]$coefficients
} else {fixeffects <- fixef(model_ptm$Model.Details$PTM[[index]])} 
ptm_estimate[ptm_estimate$GROUP=="CCCP",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]]
try(ptm_estimate[ptm_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))])
try(ptm_estimate[ptm_estimate$GROUP=="Ctrl",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Ctrl", names(fixeffects))])
try(ptm_estimate[ptm_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))])

#Protein estimated (maar nog niet adjusted)
Protein <- rep(prot, length(originalRUN))
prot_estimate <- tibble(Protein)
prot_estimate$originalRUN <- originalRUN
prot_estimate$GROUP <- GROUP
prot_estimate$FeatureType <- "Protein_estimated"
prot_estimate$LogIntensities <- NA

#Check that model estimates are definitely from that PTM
if (class(model_ptm$Model.Details$PROTEIN[[index_prot]]) == "lmerMod"){
  print(all(
  summarized_ptm$PROTEIN$ProteinLevelData %>% filter(Protein == prot) %>% pull(LogIntensities) ==
    getME(model_ptm$Model.Details$PROTEIN[[index_prot]], "y")))
}

if (class(model_ptm$Model.Details$PROTEIN[[index_prot]]) == "lm"){
fixeffects <- model_ptm$Model.Details$PROTEIN[[index_prot]]$coefficients
} else {fixeffects <- fixef(model_ptm$Model.Details$PROTEIN[[index_prot]])} 
prot_estimate[prot_estimate$GROUP=="CCCP",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]]
try(prot_estimate[prot_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))])
try(prot_estimate[prot_estimate$GROUP=="Ctrl",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Ctrl", names(fixeffects))])
try(prot_estimate[prot_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))])

#PTM normalised
Protein <- rep(i, length(originalRUN))
ptm_norm <- tibble(Protein)
ptm_norm$originalRUN <- originalRUN
ptm_norm$GROUP <- GROUP
ptm_norm$FeatureType <- "PTM_normalised"
ptm_norm$LogIntensities <- ptm_estimate$LogIntensities - prot_estimate$LogIntensities


plot_df <- rbindlist(list(protein, ptm_df, ptm_estimate, prot_estimate, ptm_norm), fill = TRUE)
plot_points <- rbindlist(list(protein, ptm_df), fill = TRUE)

#plot_df[plot_df$FeatureType == 'Model'][['FeatureType']] <- "PTM Summarized"
#plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = originalRUN, y = LogIntensities , 
                                     group = FeatureType, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
    scale_colour_manual(values = c("PTM" = "palevioletred1", "PTM_estimated" = "deeppink4", 
                                   "Protein" = "palegreen2", 
                                 "Protein_estimated" = "seagreen4",
                                 "PTM_normalised" = "goldenrod2")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=11.5),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.05)) +
  annotate("text", x = 2.5, y = 30, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 30, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 30, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 30, label = "USP30", size = 8) +
  ylim(-6, 30)

plots[[i]] <- p1
}
## [1] "A0FGR9_K608"
## [1] "A0FGR9_K608"
## [1] "B2RB47_K073"
## [1] "B2RB47_K073"
## [1] "O00154_K205"
## [1] "O00154_K205"
## [1] TRUE
## [1] "O00159_K0578"
## [1] TRUE
## [1] TRUE
## [1] "O00170_K215"
## [1] "O00170_K215"
## [1] TRUE
## [1] "O00232_K262"
## [1] "O00232_K262"
## [1] TRUE
## [1] "O00267_K0627"
## [1] "O00267_K0627"
## [1] TRUE
## [1] "O00410_K0806"
## [1] TRUE
## [1] TRUE
## [1] "O14972_K103"
## [1] TRUE
## [1] "O14980_K0686"
## [1] "O14980_K0686"
## [1] TRUE
## [1] "O15372_K274"
## [1] "O15372_K274"
## [1] TRUE
## [1] "O43175_K289"
## [1] TRUE
## [1] TRUE
## [1] "O43670_K100"
## [1] TRUE
## [1] "O43847_K0993"
## [1] "O43847_K0993"
## [1] "O60260_K076"
## [1] TRUE
## [1] TRUE
## [1] "O60260_K220"
## [1] TRUE
## [1] TRUE
## [1] "O60260_K369"
## [1] TRUE
## [1] TRUE
## [1] "O60260_K408"
## [1] TRUE
## [1] TRUE
## [1] "O60260_K435"
## [1] "O60260_K435"
## [1] TRUE
## [1] "O60341_K492"
## [1] "O60341_K492"
## [1] "O60361_K034"
## [1] "O60361_K034"
## [1] TRUE
## [1] "O60361_K041"
## [1] TRUE
## [1] TRUE
## [1] "O60361_K070"
## [1] "O60361_K070"
## [1] TRUE
## [1] "O60361_K109"
## [1] TRUE
## [1] TRUE
## [1] "O60361_K113"
## [1] "O60361_K113"
## Error : Assigned data `fixeffects[["(Intercept)"]] + ...` must be compatible with existing data.
## ✖ Existing data has 4 rows.
## ✖ Assigned data has 0 rows.
## ℹ Only vectors of size 1 are recycled.
## [1] TRUE
## [1] "O60506_K336"
## [1] TRUE
## [1] TRUE
## [1] "O60749_K218"
## [1] TRUE
## [1] "O60749_K516"
## [1] "O60749_K516"
## [1] "O60832_K433"
## [1] "O60832_K433"
## [1] TRUE
## [1] "O60888_K082"
## [1] "O60888_K082"
## [1] TRUE
## [1] "O75131_K158"
## [1] "O75131_K158"
## Error : Assigned data `fixeffects[["(Intercept)"]] + ...` must be compatible with existing data.
## ✖ Existing data has 4 rows.
## ✖ Assigned data has 0 rows.
## ℹ Only vectors of size 1 are recycled.
## [1] "O75150_K440"
## [1] "O75150_K440"
## Error : Assigned data `fixeffects[["(Intercept)"]] + ...` must be compatible with existing data.
## ✖ Existing data has 4 rows.
## ✖ Assigned data has 0 rows.
## ℹ Only vectors of size 1 are recycled.
## [1] "O75400_K669"
## [1] "O75400_K669"
## [1] TRUE
## [1] "O75694_K0740"
## [1] TRUE
## [1] "O75694_K0824"
## [1] "O75694_K0824"
## [1] "O75694_K0890"
## [1] "O75694_K0890"
## [1] "O75694_K0902"
## [1] TRUE
## [1] "O75694_K0987"
## [1] TRUE
## [1] "O75694_K1069"
## [1] "O75694_K1069"
## [1] "O75694_K1126"
## [1] TRUE
plots
## $A0FGR9_K608
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $B2RB47_K073
## Warning: Removed 10 row(s) containing missing values (geom_path).
## Warning: Removed 9 rows containing missing values (geom_point).

## 
## $O00154_K205
## Warning: Removed 1 rows containing missing values (geom_point).

## 
## $O00159_K0578

## 
## $O00170_K215

## 
## $O00232_K262

## 
## $O00267_K0627

## 
## $O00410_K0806

## 
## $O14972_K103
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $O14980_K0686
## Warning: Removed 1 row(s) containing missing values (geom_path).
## Warning: Removed 4 rows containing missing values (geom_point).

## 
## $O15372_K274
## Warning: Removed 1 rows containing missing values (geom_point).

## 
## $O43175_K289

## 
## $O43670_K100
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $O43847_K0993
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O60260_K076

## 
## $O60260_K220

## 
## $O60260_K369

## 
## $O60260_K408

## 
## $O60260_K435

## 
## $O60341_K492
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 9 rows containing missing values (geom_point).

## 
## $O60361_K034

## 
## $O60361_K041

## 
## $O60361_K070

## 
## $O60361_K109

## 
## $O60361_K113

## 
## $O60506_K336

## 
## $O60749_K218
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $O60749_K516
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O60832_K433
## Warning: Removed 1 rows containing missing values (geom_point).

## 
## $O60888_K082

## 
## $O75131_K158
## Warning: Removed 14 row(s) containing missing values (geom_path).
## Warning: Removed 11 rows containing missing values (geom_point).

## 
## $O75150_K440
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Removed 11 rows containing missing values (geom_point).

## 
## $O75400_K669

## 
## $O75694_K0740
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $O75694_K0824
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O75694_K0890
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O75694_K0902
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O75694_K0987
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O75694_K1069
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

## 
## $O75694_K1126
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Removed 8 rows containing missing values (geom_point).

model_ptm$ADJUSTED.Model %>% filter(Protein == "O60260_K369", Label == "Combo vs Ctrl")

2 Msqrob

estimated ptm abundance -> rowData(pe[[“ptmRel”]])\(msqrobModels\)P18124_K029 %>% getCoef() protein abundance -> assay(pe[[“proteinRobust”]]) ptm abundance -> this I do not have, is already normalised normalised ptm abundance -> assay(pe[[“ptmRel”]])

## Plot ptm's from Combo vs Ctrl
ptm_list2 <- rowData(pe[["ptmRel"]])$groupCombo %>% filter(adjPval <= 0.05) %>% rownames()
plots <- c()
for (i in ptm_list2){
  print(i)
  prot <- strsplit(i, "_")[[1]][1]

#Protein abundance
protein <- assay(pe[["proteinRaw"]])[prot,] %>% as.data.frame() 
colnames(protein) <- "LogIntensities"
protein <- protein %>%
  mutate(Protein = prot,
         FeatureType = "Protein",
         GROUP = sapply(strsplit(rownames(protein), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP, originalRUN)

#Peptidoform abundance
pepforms <- rowData(pe[["peptidoformRaw"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
pepform <- assay(pe[["peptidoformRaw"]])[pepforms,] %>% as.data.frame()
if (length(pepforms)==0) {next}
if (length(pepforms)>1){
  pepform <- pepform %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform$GROUP <- sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1])
  pepform <- pepform %>% arrange(GROUP, originalRUN)
} else {colnames(pepform) <- "LogIntensities"
        pepform <- pepform %>% rownames_to_column("originalRUN") 
        pepform <- pepform %>% mutate(GROUP = 
                    sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1]),
                    Protein = pepforms[1]) %>%
                   arrange(GROUP, originalRUN)
        }
pepform <- pepform %>%
  mutate(FeatureType = "Peptidoform")
#pepform <- select(-c("pepform"))
pepform$originalRUN <- forcats::fct_inorder(pepform$originalRUN)

#Peptidoform abundance - normalised
pepforms <- rowData(pe[["pepformRel"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
pepform_norm <- assay(pe[["pepformRel"]])[pepforms,] %>% as.data.frame()
if (length(pepforms)>1){
  pepform_norm <- pepform_norm %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform_norm), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform_norm$GROUP <- sapply(strsplit(pepform_norm$originalRUN, "-"), function(x) x[1])
  pepform_norm <- pepform_norm %>% arrange(GROUP, originalRUN) %>%
    mutate(Protein = paste(Protein,"norm"))
} else {colnames(pepform_norm) <- "LogIntensities"
        pepform_norm <- pepform_norm %>% rownames_to_column("originalRUN") 
        pepform_norm <- pepform_norm %>% mutate(GROUP = 
                    sapply(strsplit(pepform_norm$originalRUN, "-"), function(x) x[1]),
                    Protein = paste(pepforms[1],"norm")) %>%
                   arrange(GROUP, originalRUN)
        }
pepform_norm <- pepform_norm %>%
  mutate(FeatureType = "Peptidoform - normalised")
#pepform <- select(-c("pepform"))
pepform_norm$originalRUN <- forcats::fct_inorder(pepform_norm$originalRUN)

#Normalised PTM abundance
ptm_df <- assay(pe[["ptmRel"]])[i,] %>% as.data.frame()
colnames(ptm_df) <- "LogIntensities"
ptm_df <- ptm_df %>%
  mutate(Protein = i,
         FeatureType = "PTM - normalised",
         GROUP = sapply(strsplit(rownames(ptm_df), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP, originalRUN)


#PTM estimated
Protein <- paste(rep(i, nrow(ptm_df)), "estimate")
ptm_estimate <- tibble(Protein)
ptm_estimate$originalRUN <- ptm_df$originalRUN
ptm_estimate$GROUP <- ptm_df$GROUP
ptm_estimate$FeatureType <- "PTM_estimated"
ptm_estimate$LogIntensities <- NA

fixeffects <- rowData(pe[["ptmRel"]])$msqrobModels[[i]] %>% getCoef
ptm_estimate[ptm_estimate$GROUP=="Ctrl",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]]
ptm_estimate[ptm_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="CCCP",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("CCCP", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))][1]
ptm_estimate <- ptm_estimate %>% arrange(GROUP, originalRUN)

plot_df <- rbindlist(list(protein, pepform, pepform_norm, ptm_df, ptm_estimate), fill = TRUE)
plot_df$originalRUN <- forcats::fct_inorder(plot_df$originalRUN)
plot_points <- plot_df %>% filter(FeatureType != "PTM_estimated")

#plot_df[plot_df$FeatureType == 'Model'][['FeatureType']] <- "PTM Summarized"
#plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("Peptidoform - normalised" = "#C3C3C3", 
                                 "Protein" = "dodgerblue2", "PTM - normalised" = "seagreen3", 
                                 "PTM_estimated" = "palevioletred2", "Peptidoform" = "gray36"))  +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.05)) +
  annotate("text", x = 2.5, y = 30, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 30, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 30, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 30, label = "USP30", size = 8) +
  ylim(-5, 30)

plots[[i]] <- p1
}
## [1] "O43242_K273"
## [1] "O94826_K168"
## [1] "O94826_K300"
## [1] "O94826_K078"
## [1] "P00387_K115"
## [1] "P05023_K0671"
## [1] "P05023_K0727"
## [1] "P14618_K207"
## [1] "P19367_K501"
## [1] "P21333_K0906"
## [1] "P36578_K106"
## [1] "P46777_K027"
## [1] "P46781_K121"
## [1] "P52789_K041"
## [1] "P54920_K227"
## [1] "P56937_K321"
## [1] "P60174_K051"
## [1] "P61247_K056"
## [1] "P61978_K052"
## [1] "Q00610_K0911"
## [1] "Q13332_K1685"
## [1] "Q13485_K070"
## [1] "Q14566_K611"
## [1] "Q15154_K0970"
## [1] "Q8WXW3_K708"
## [1] "Q969Z3_K294"
## [1] "Q99613_K712"
## [1] "Q9NZ45_K089"
## [1] "Q9UHP3_K0201"
## [1] "Q9Y490_K0334"
plots
## $O43242_K273

## 
## $O94826_K168
## Warning: Removed 26 row(s) containing missing values (geom_path).
## Warning: Removed 44 rows containing missing values (geom_point).

## 
## $O94826_K300
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O94826_K078
## Warning: Removed 10 row(s) containing missing values (geom_path).
## Warning: Removed 39 rows containing missing values (geom_point).

## 
## $P00387_K115
## Warning: Removed 42 row(s) containing missing values (geom_path).
## Warning: Removed 69 rows containing missing values (geom_point).

## 
## $P05023_K0671
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 17 rows containing missing values (geom_point).

## 
## $P05023_K0727
## Warning: Removed 6 rows containing missing values (geom_point).

## 
## $P14618_K207
## Warning: Removed 14 row(s) containing missing values (geom_path).
## Warning: Removed 32 rows containing missing values (geom_point).

## 
## $P19367_K501
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 11 rows containing missing values (geom_point).

## 
## $P21333_K0906
## Warning: Removed 6 rows containing missing values (geom_point).

## 
## $P36578_K106
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $P46777_K027

## 
## $P46781_K121
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $P52789_K041
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $P54920_K227

## 
## $P56937_K321
## Warning: Removed 23 row(s) containing missing values (geom_path).
## Warning: Removed 27 rows containing missing values (geom_point).

## 
## $P60174_K051
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $P61247_K056
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $P61978_K052

## 
## $Q00610_K0911

## 
## $Q13332_K1685
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $Q13485_K070

## 
## $Q14566_K611

## 
## $Q15154_K0970
## Warning: Removed 14 row(s) containing missing values (geom_path).
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $Q8WXW3_K708
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $Q969Z3_K294
## Warning: Removed 40 row(s) containing missing values (geom_path).
## Warning: Removed 56 rows containing missing values (geom_point).

## 
## $Q99613_K712

## 
## $Q9NZ45_K089
## Warning: Removed 70 row(s) containing missing values (geom_path).
## Warning: Removed 114 rows containing missing values (geom_point).

## 
## $Q9UHP3_K0201
## Warning: Removed 24 row(s) containing missing values (geom_path).
## Warning: Removed 52 rows containing missing values (geom_point).

## 
## $Q9Y490_K0334
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 4 rows containing missing values (geom_point).

2.0.1 CCCP vs Ctrl

## Plot ptm's from CCCP vs Ctrl
ptm_listCCCP <- rowData(pe[["ptmRel"]])$groupCCCP %>% filter(adjPval <= 0.05) %>% rownames()
plots <- c()
for (i in ptm_listCCCP){
  print(i)
  prot <- strsplit(i, "_")[[1]][1]

#Protein abundance
protein <- assay(pe[["proteinRaw"]])[prot,] %>% as.data.frame() 
colnames(protein) <- "LogIntensities"
protein <- protein %>%
  mutate(Protein = prot,
         FeatureType = "Protein",
         GROUP = sapply(strsplit(rownames(protein), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP, originalRUN)

#Peptidoform abundance
pepforms <- rowData(pe[["peptidoformRaw"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
pepform <- assay(pe[["peptidoformRaw"]])[pepforms,] %>% as.data.frame()
if (length(pepforms)==0) {next}
if (length(pepforms)>1){
  pepform <- pepform %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform$GROUP <- sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1])
  pepform <- pepform %>% arrange(GROUP, originalRUN)
} else {colnames(pepform) <- "LogIntensities"
        pepform <- pepform %>% rownames_to_column("originalRUN") 
        pepform <- pepform %>% mutate(GROUP = 
                    sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1]),
                    Protein = pepforms[1]) %>%
                   arrange(GROUP, originalRUN)
        }
pepform <- pepform %>%
  mutate(FeatureType = "Peptidoform")
#pepform <- select(-c("pepform"))
pepform$originalRUN <- forcats::fct_inorder(pepform$originalRUN)

#Peptidoform abundance - normalised
pepforms <- rowData(pe[["pepformRel"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
pepform_norm <- assay(pe[["pepformRel"]])[pepforms,] %>% as.data.frame()
if (length(pepforms)>1){
  pepform_norm <- pepform_norm %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform_norm), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform_norm$GROUP <- sapply(strsplit(pepform_norm$originalRUN, "-"), function(x) x[1])
  pepform_norm <- pepform_norm %>% arrange(GROUP, originalRUN) %>%
    mutate(Protein = paste(Protein,"norm"))
} else {colnames(pepform_norm) <- "LogIntensities"
        pepform_norm <- pepform_norm %>% rownames_to_column("originalRUN") 
        pepform_norm <- pepform_norm %>% mutate(GROUP = 
                    sapply(strsplit(pepform_norm$originalRUN, "-"), function(x) x[1]),
                    Protein = paste(pepforms[1],"norm")) %>%
                   arrange(GROUP, originalRUN)
        }
pepform_norm <- pepform_norm %>%
  mutate(FeatureType = "Peptidoform - normalised")
#pepform <- select(-c("pepform"))
pepform_norm$originalRUN <- forcats::fct_inorder(pepform_norm$originalRUN)

#Normalised PTM abundance
ptm_df <- assay(pe[["ptmRel"]])[i,] %>% as.data.frame()
colnames(ptm_df) <- "LogIntensities"
ptm_df <- ptm_df %>%
  mutate(Protein = i,
         FeatureType = "PTM - normalised",
         GROUP = sapply(strsplit(rownames(ptm_df), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP, originalRUN)


#PTM estimated
Protein <- paste(rep(i, nrow(ptm_df)), "estimate")
ptm_estimate <- tibble(Protein)
ptm_estimate$originalRUN <- ptm_df$originalRUN
ptm_estimate$GROUP <- ptm_df$GROUP
ptm_estimate$FeatureType <- "PTM_estimated"
ptm_estimate$LogIntensities <- NA

fixeffects <- rowData(pe[["ptmRel"]])$msqrobModels[[i]] %>% getCoef
ptm_estimate[ptm_estimate$GROUP=="Ctrl",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]]
ptm_estimate[ptm_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="CCCP",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("CCCP", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))][1]
ptm_estimate <- ptm_estimate %>% arrange(GROUP, originalRUN)

plot_df <- rbindlist(list(protein, pepform, pepform_norm, ptm_df, ptm_estimate), fill = TRUE)
plot_df$originalRUN <- forcats::fct_inorder(plot_df$originalRUN)
plot_points <- plot_df %>% filter(FeatureType != "PTM_estimated")

#plot_df[plot_df$FeatureType == 'Model'][['FeatureType']] <- "PTM Summarized"
#plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("Peptidoform - normalised" = "#C3C3C3", 
                                 "Protein" = "dodgerblue2", "PTM - normalised" = "seagreen3", 
                                 "PTM_estimated" = "palevioletred2", "Peptidoform" = "gray36"))  +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.05)) +
  annotate("text", x = 2.5, y = 30, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 30, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 30, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 30, label = "USP30", size = 8) +
  ylim(-5, 30)

plots[[i]] <- p1
}
## [1] "O94826_K168"
## [1] "O94826_K300"
## [1] "P00387_K115"
## [1] "P05023_K0727"
## [1] "P14618_K207"
## [1] "P19367_K501"
## [1] "P61247_K056"
## [1] "Q14566_K611"
## [1] "Q15154_K0970"
## [1] "Q9BYC9_K114"
## [1] "Q9UHP3_K0201"
## [1] "Q9Y490_K0334"
plots
## $O94826_K168
## Warning: Removed 26 row(s) containing missing values (geom_path).
## Warning: Removed 44 rows containing missing values (geom_point).

## 
## $O94826_K300
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $P00387_K115
## Warning: Removed 42 row(s) containing missing values (geom_path).
## Warning: Removed 69 rows containing missing values (geom_point).

## 
## $P05023_K0727
## Warning: Removed 6 rows containing missing values (geom_point).

## 
## $P14618_K207
## Warning: Removed 14 row(s) containing missing values (geom_path).
## Warning: Removed 32 rows containing missing values (geom_point).

## 
## $P19367_K501
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 11 rows containing missing values (geom_point).

## 
## $P61247_K056
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $Q14566_K611

## 
## $Q15154_K0970
## Warning: Removed 14 row(s) containing missing values (geom_path).
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $Q9BYC9_K114
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $Q9UHP3_K0201
## Warning: Removed 24 row(s) containing missing values (geom_path).
## Warning: Removed 52 rows containing missing values (geom_point).

## 
## $Q9Y490_K0334
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 4 rows containing missing values (geom_point).

plots <- list()
for (i in ptm_list2){
prot_ = str_split(i, "_")[[1]][1]
site_ = str_split(i, "_")[[1]][2]

pepform_df <- longFormat(pe[,,"pepformRel"], rowvars = c("protein", "ptm"), colvars = c("group")) %>% as.data.frame()
pepform_df <- pepform_df %>% filter(protein == prot_)
pepform_df <- pepform_df %>% filter(grepl(site_, ptm, fixed = T))
pepform_df$FeatureType <- "Peptide"
pepform_df <- pepform_df %>% arrange(group, rowname)

ptm_df <- longFormat(pe[,,"ptmRel"], rowvars = c("protein", "ptm"), colvars = c("group")) %>% as.data.frame()
ptm_df <- ptm_df %>% filter(ptm == i)
ptm_df$FeatureType <- "PTM"
ptm_df <- ptm_df %>% arrange(group, rowname)

plot_df <- rbindlist(list(pepform_df, ptm_df), fill = TRUE)

plot_df[plot_df$FeatureType == 'PTM'][['FeatureType']] <- "PTM Summarized"
plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"
plot_df$primary <- forcats::fct_inorder(plot_df$primary)

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = primary, y = value , group = rowname, color = FeatureType), size =2) +
  geom_point(aes(x = primary, y = value , group = rowname, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("#C3C3C3", "#D55E00")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "Abundance") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0)) +
  annotate("text", x = 2.5, y = 6.5, label = "Ctrl", size = 6) +
  annotate("text", x = 6.5, y = 6.5, label = "CCCP", size = 6) +
  annotate("text", x = 10.5, y = 6.5, label = "Combo", size = 6) +
  annotate("text", x = 14.5, y = 6.5, label = "USP30", size = 6) +
  ylim(-6, 6.5)

plots[[i]] <- p1
}
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 128 sampleMap rows not in names(experiments)
plots
## $O43242_K273

## 
## $O94826_K168
## Warning: Removed 12 row(s) containing missing values (geom_path).
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $O94826_K300
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 9 rows containing missing values (geom_point).

## 
## $O94826_K078
## Warning: Removed 7 row(s) containing missing values (geom_path).
## Warning: Removed 20 rows containing missing values (geom_point).

## 
## $P00387_K115
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 33 rows containing missing values (geom_point).

## 
## $P05023_K0671
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 12 rows containing missing values (geom_point).

## 
## $P05023_K0727
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 4 rows containing missing values (geom_point).

## 
## $P14618_K207
## Warning: Removed 11 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $P19367_K501
## Warning: Removed 1 row(s) containing missing values (geom_path).
## Warning: Removed 6 rows containing missing values (geom_point).

## 
## $P21333_K0906
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $P36578_K106
## Warning: Removed 1 rows containing missing values (geom_point).

## 
## $P46777_K027

## 
## $P46781_K121
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 12 rows containing missing values (geom_point).

## 
## $P52789_K041
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $P54920_K227

## 
## $P56937_K321
## Warning: Removed 12 row(s) containing missing values (geom_path).
## Warning: Removed 14 rows containing missing values (geom_point).

## 
## $P60174_K051
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $P61247_K056
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $P61978_K052

## 
## $Q00610_K0911

## 
## $Q13332_K1685
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $Q13485_K070

## 
## $Q14566_K611

## 
## $Q15154_K0970
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 11 rows containing missing values (geom_point).

## 
## $Q8WXW3_K708
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $Q969Z3_K294
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 28 rows containing missing values (geom_point).

## 
## $Q99613_K712

## 
## $Q9NZ45_K089
## Warning: Removed 37 row(s) containing missing values (geom_path).
## Warning: Removed 57 rows containing missing values (geom_point).

## 
## $Q9UHP3_K0201
## Warning: Removed 2 row(s) containing missing values (geom_path).
## Warning: Removed 26 rows containing missing values (geom_point).

## 
## $Q9Y490_K0334
## Warning: Removed 4 rows containing missing values (geom_point).

2.0.2 For MSstats significant ptms

Plots of MSstats first 40 significant PTMs

## Plot fourty ptm's from Combo vs Ctrl
plots <- c()
for (i in ptm_list1){
  print(i)
  if(!i %in% rownames(assay(pe[["ptmRel"]]))){
    print(paste(i, "not in msqrob"))
    next
    }
  if(i %in% ptm_list2){print(paste(i, "also significant with msqrob"))}
  prot <- strsplit(i, "_")[[1]][1]

#Protein abundance
protein <- assay(pe[["proteinRaw"]])[prot,] %>% as.data.frame() 
colnames(protein) <- "LogIntensities"
protein <- protein %>%
  mutate(Protein = prot,
         FeatureType = "Protein",
         GROUP = sapply(strsplit(rownames(protein), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP)

#Peptidoform abundance
pepforms <- rowData(pe[["pepformRel"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
pepform <- assay(pe[["pepformRel"]])[pepforms,] %>% as.data.frame()
if((nrow(rowData(pe[["peptidoformRaw"]]) %>% as.data.frame() %>% 
         filter(ptm == i))==0)){next}
if (length(pepforms)==0){
  print(paste(i, "not in normalised PTM data"))
  pepforms <- rowData(pe[["peptidoformRaw"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
  pepform <- assay(pe[["peptidoformRaw"]])[pepforms,] %>% as.data.frame()
  if (length(pepforms)>1){
  pepform <- pepform %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform$GROUP <- sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1])
  pepform <- pepform %>% arrange(pepform, GROUP)
} else {colnames(pepform) <- "LogIntensities"
        pepform <- pepform %>% rownames_to_column("originalRUN") 
        pepform <- pepform %>% mutate(GROUP = 
                    sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1]),
                    Protein = pepforms[1]) %>%
                   arrange(GROUP)
        }
  pepform <- pepform %>%
  mutate(FeatureType = "pepform - unnormalised")
  plot_df <- rbindlist(list(protein, pepform), fill = TRUE)
  p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size =2) +
  geom_point(aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("pepform - unnormalised" = "lightgoldenrod", "Protein" = "palegreen2", 
                                 "PTM" = "palevioletred2", "PTM_estimated" = "deeppink4")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = paste(i, "no normalisation possible"), x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.05)) +
  annotate("text", x = 2.5, y = 27, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 27, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 27, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 27, label = "USP30", size = 8) +
  ylim(-7, 27)

plots[[i]] <- p1
next
}
if (length(pepforms)>1){
  pepform <- pepform %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform$GROUP <- sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1])
  pepform <- pepform %>% arrange(pepform, GROUP) %>%
    mutate(Protein = paste(Protein, "normalised"))
} else {colnames(pepform) <- "LogIntensities"
        pepform <- pepform %>% rownames_to_column("originalRUN") 
        pepform <- pepform %>% mutate(GROUP = 
                    sapply(strsplit(pepform$originalRUN, "-"), function(x) x[1]),
                    Protein = paste(pepforms[1], "normalised")) %>%
                   arrange(GROUP)
        }
pepform <- pepform %>%
  mutate(FeatureType = "Peptidoform - Normalised")

pepform$originalRUN <- forcats::fct_inorder(pepform$originalRUN)

pepforms_raw <- rowData(pe[["peptidoformRaw"]]) %>% as.data.frame() %>% 
    filter(ptm == i) %>% rownames
pepform_raw <- assay(pe[["peptidoformRaw"]])[pepforms_raw,] %>% as.data.frame()
if (length(pepforms_raw)>1){
  pepform_raw <- pepform_raw %>% rownames_to_column("Protein") %>% 
    pivot_longer(cols = colnames(pepform_raw), names_to = "originalRUN",
                 values_to = "LogIntensities") 
  pepform_raw$GROUP <- sapply(strsplit(pepform_raw$originalRUN, "-"), function(x) x[1])
  pepform_raw <- pepform_raw %>% arrange(pepform_raw, GROUP)
} else {colnames(pepform_raw) <- "LogIntensities"
        pepform_raw <- pepform_raw %>% rownames_to_column("originalRUN") 
        pepform_raw <- pepform_raw %>% mutate(GROUP = 
                    sapply(strsplit(pepform_raw$originalRUN, "-"), function(x) x[1]),
                    Protein = pepforms_raw[1]) %>%
                   arrange(GROUP)
        }
pepform_raw <- pepform_raw %>%
  mutate(FeatureType = "Peptidoform")


#Normalised PTM abundance
ptm_df <- assay(pe[["ptmRel"]])[i,] %>% as.data.frame()
colnames(ptm_df) <- "LogIntensities"
ptm_df <- ptm_df %>%
  mutate(Protein = i,
         FeatureType = "PTM - normalised",
         GROUP = sapply(strsplit(rownames(ptm_df), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP)


#PTM estimated
Protein <- paste(rep(i, nrow(ptm_df)), "estimate")
ptm_estimate <- tibble(Protein)
ptm_estimate$originalRUN <- ptm_df$originalRUN
ptm_estimate$GROUP <- ptm_df$GROUP
ptm_estimate$FeatureType <- "PTM_estimated"
ptm_estimate$LogIntensities <- NA

fixeffects <- rowData(pe[["ptmRel"]])$msqrobModels[[i]] %>% getCoef
if (! all(is.finite(fixeffects))){print(paste(i, "no refitting possible"))
  next}
ptm_estimate[ptm_estimate$GROUP=="Ctrl",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]]
ptm_estimate[ptm_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="CCCP",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("CCCP", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))][1]


plot_df <- rbindlist(list(protein, pepform, ptm_df, ptm_estimate, pepform_raw), fill = TRUE)
plot_df$originalRUN <- as.vector(plot_df$originalRUN)
plot_df <- plot_df %>% arrange(FeatureType, originalRUN)
plot_df$originalRUN <- forcats::fct_inorder(plot_df$originalRUN)
plot_points <- plot_df %>% filter(FeatureType != "PTM_estimated")

#plot_df[plot_df$FeatureType == 'Model'][['FeatureType']] <- "PTM Summarized"
#plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = originalRUN, y = LogIntensities , group = Protein, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("Peptidoform - normalised" = "#C3C3C3", 
                                 "Protein" = "palegreen2", "PTM - normalised" = "goldenrod2", 
                                 "PTM_estimated" = "deeppink4", "Peptidoform" = "gray36"))+
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=11.3),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.05)) +
  annotate("text", x = 2.5, y = 30, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 30, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 30, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 30, label = "USP30", size = 8) +
  ylim(-5, 30)

plots[[i]] <- p1
}
## [1] "A0FGR9_K608"
## [1] "A0FGR9_K608 not in msqrob"
## [1] "B2RB47_K073"
## [1] "B2RB47_K073 not in msqrob"
## [1] "O00154_K205"
## [1] "O00159_K0578"
## [1] "O00170_K215"
## [1] "O00232_K262"
## [1] "O00267_K0627"
## [1] "O00410_K0806"
## [1] "O14972_K103"
## [1] "O14980_K0686"
## [1] "O15372_K274"
## [1] "O43175_K289"
## [1] "O43670_K100"
## [1] "O43847_K0993"
## [1] "O60260_K076"
## [1] "O60260_K220"
## [1] "O60260_K369"
## [1] "O60260_K408"
## [1] "O60260_K435"
## [1] "O60341_K492"
## [1] "O60361_K034"
## [1] "O60361_K041"
## [1] "O60361_K070"
## [1] "O60361_K109"
## [1] "O60361_K113"
## [1] "O60361_K113 no refitting possible"
## [1] "O60506_K336"
## [1] "O60749_K218"
## [1] "O60749_K516"
## [1] "O60832_K433"
## [1] "O60888_K082"
## [1] "O75131_K158"
## [1] "O75150_K440"
## [1] "O75400_K669"
## [1] "O75694_K0740"
## [1] "O75694_K0824"
## [1] "O75694_K0890"
## [1] "O75694_K0902"
## [1] "O75694_K0987"
## [1] "O75694_K1069"
## [1] "O75694_K1126"
plots
## $O00154_K205
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O00159_K0578
## Warning: Removed 9 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O00170_K215
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 27 rows containing missing values (geom_point).

## 
## $O00232_K262
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Removed 27 rows containing missing values (geom_point).

## 
## $O00267_K0627
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O00410_K0806
## Warning: Removed 40 row(s) containing missing values (geom_path).
## Warning: Removed 92 rows containing missing values (geom_point).

## 
## $O14972_K103
## Warning: Removed 3 row(s) containing missing values (geom_path).
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $O14980_K0686
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O15372_K274
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 27 rows containing missing values (geom_point).

## 
## $O43175_K289
## Warning: Removed 6 rows containing missing values (geom_point).

## 
## $O43670_K100
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $O43847_K0993
## Warning: Removed 8 row(s) containing missing values (geom_path).
## Warning: Removed 35 rows containing missing values (geom_point).

## 
## $O60260_K076
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 15 rows containing missing values (geom_point).

## 
## $O60260_K220
## Warning: Removed 12 row(s) containing missing values (geom_path).
## Warning: Removed 46 rows containing missing values (geom_point).

## 
## $O60260_K369

## 
## $O60260_K408
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O60260_K435
## Warning: Removed 16 row(s) containing missing values (geom_path).
## Warning: Removed 60 rows containing missing values (geom_point).

## 
## $O60341_K492
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 27 rows containing missing values (geom_point).

## 
## $O60361_K034
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Removed 27 rows containing missing values (geom_point).

## 
## $O60361_K041
## Warning: Removed 8 row(s) containing missing values (geom_path).
## Warning: Removed 34 rows containing missing values (geom_point).

## 
## $O60361_K070
## Warning: Removed 40 row(s) containing missing values (geom_path).
## Warning: Removed 71 rows containing missing values (geom_point).

## 
## $O60361_K109
## Warning: Removed 14 row(s) containing missing values (geom_path).
## Warning: Removed 30 rows containing missing values (geom_point).

## 
## $O60506_K336
## Warning: Removed 6 rows containing missing values (geom_point).

## 
## $O60749_K218
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $O60749_K516
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O60832_K433
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 25 rows containing missing values (geom_point).

## 
## $O60888_K082
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 27 rows containing missing values (geom_point).

## 
## $O75131_K158
## Warning: Removed 10 row(s) containing missing values (geom_path).
## Warning: Removed 40 rows containing missing values (geom_point).

## 
## $O75150_K440
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O75400_K669
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Removed 24 rows containing missing values (geom_point).

## 
## $O75694_K0740
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $O75694_K0824
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O75694_K0890
## Warning: Removed 10 row(s) containing missing values (geom_path).
## Warning: Removed 45 rows containing missing values (geom_point).

## 
## $O75694_K0902
## Warning: Removed 3 rows containing missing values (geom_point).

## 
## $O75694_K0987
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 23 rows containing missing values (geom_point).

## 
## $O75694_K1069
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 27 rows containing missing values (geom_point).

## 
## $O75694_K1126
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 22 rows containing missing values (geom_point).

for (i in ptm_list1){
  print(i)
  if(!i %in% rownames(assay(pe[["ptmRel"]]))){
    print(paste(i, "not in msqrob"))
    next
    }
  print(rowData(pe[["ptmRel"]])$groupCombo[i,])
  }
## [1] "A0FGR9_K608"
## [1] "A0FGR9_K608 not in msqrob"
## [1] "B2RB47_K073"
## [1] "B2RB47_K073 not in msqrob"
## [1] "O00154_K205"
##             logFC se       df  t pval adjPval
## O00154_K205    NA NA 5.561565 NA   NA      NA
## [1] "O00159_K0578"
##              logFC se       df  t pval adjPval
## O00159_K0578    NA NA 6.566507 NA   NA      NA
## [1] "O00170_K215"
##             logFC se       df  t pval adjPval
## O00170_K215    NA NA 4.561565 NA   NA      NA
## [1] "O00232_K262"
##             logFC se       df  t pval adjPval
## O00232_K262    NA NA 4.561565 NA   NA      NA
## [1] "O00267_K0627"
##              logFC se       df  t pval adjPval
## O00267_K0627    NA NA 5.561565 NA   NA      NA
## [1] "O00410_K0806"
##                 logFC        se       df        t        pval   adjPval
## O00410_K0806 1.770579 0.5540462 11.23528 3.195725 0.008308075 0.3435982
## [1] "O14972_K103"
##                  logFC       se       df          t      pval adjPval
## O14972_K103 -0.3065211 1.961715 9.431339 -0.1562516 0.8791284       1
## [1] "O14980_K0686"
##              logFC se       df  t pval adjPval
## O14980_K0686    NA NA 5.561565 NA   NA      NA
## [1] "O15372_K274"
##             logFC se       df  t pval adjPval
## O15372_K274    NA NA 4.561565 NA   NA      NA
## [1] "O43175_K289"
##             logFC se       df  t pval adjPval
## O43175_K289    NA NA 9.837067 NA   NA      NA
## [1] "O43670_K100"
##                  logFC        se       df         t      pval adjPval
## O43670_K100 0.06658972 0.1662865 11.00365 0.4004519 0.6964889       1
## [1] "O43847_K0993"
##              logFC se       df  t pval adjPval
## O43847_K0993    NA NA 4.561565 NA   NA      NA
## [1] "O60260_K076"
##                 logFC       se       df         t      pval adjPval
## O60260_K076 0.9880622 1.108285 9.473871 0.8915238 0.3947268       1
## [1] "O60260_K220"
##                logFC       se       df        t      pval adjPval
## O60260_K220 1.105436 1.265646 10.37847 0.873417 0.4021929       1
## [1] "O60260_K369"
##                  logFC        se       df         t     pval adjPval
## O60260_K369 -0.5466616 0.3494623 11.87849 -1.564294 0.143986       1
## [1] "O60260_K408"
##                logFC        se       df        t       pval   adjPval
## O60260_K408 1.441877 0.6890223 10.47664 2.092643 0.06160434 0.9415948
## [1] "O60260_K435"
##             logFC se       df  t pval adjPval
## O60260_K435    NA NA 5.561565 NA   NA      NA
## [1] "O60341_K492"
##             logFC se       df  t pval adjPval
## O60341_K492    NA NA 4.561565 NA   NA      NA
## [1] "O60361_K034"
##             logFC se       df  t pval adjPval
## O60361_K034    NA NA 4.561565 NA   NA      NA
## [1] "O60361_K041"
##                  logFC        se       df         t      pval adjPval
## O60361_K041 -0.3289675 0.6228605 10.52565 -0.528156 0.6083458       1
## [1] "O60361_K070"
##             logFC se       df  t pval adjPval
## O60361_K070    NA NA 5.561565 NA   NA      NA
## [1] "O60361_K109"
##                logFC       se       df         t      pval adjPval
## O60361_K109 1.091522 1.167485 10.39397 0.9349342 0.3710344       1
## [1] "O60361_K113"
##             logFC se df  t pval adjPval
## O60361_K113    NA NA NA NA   NA      NA
## [1] "O60506_K336"
##                logFC       se       df        t      pval adjPval
## O60506_K336 5.267339 4.133408 8.609018 1.274333 0.2358665       1
## [1] "O60749_K218"
##                 logFC        se       df         t      pval adjPval
## O60749_K218 0.0931323 0.3960529 9.755213 0.2351512 0.8189539       1
## [1] "O60749_K516"
##             logFC se       df  t pval adjPval
## O60749_K516    NA NA 5.561565 NA   NA      NA
## [1] "O60832_K433"
##             logFC se       df  t pval adjPval
## O60832_K433    NA NA 5.561565 NA   NA      NA
## [1] "O60888_K082"
##             logFC se       df  t pval adjPval
## O60888_K082    NA NA 4.561565 NA   NA      NA
## [1] "O75131_K158"
##             logFC se       df  t pval adjPval
## O75131_K158    NA NA 5.561565 NA   NA      NA
## [1] "O75150_K440"
##             logFC se       df  t pval adjPval
## O75150_K440    NA NA 5.561565 NA   NA      NA
## [1] "O75400_K669"
##             logFC se       df  t pval adjPval
## O75400_K669    NA NA 5.561565 NA   NA      NA
## [1] "O75694_K0740"
##                   logFC       se       df          t      pval adjPval
## O75694_K0740 -0.7723166 1.695731 10.37557 -0.4554475 0.6581702       1
## [1] "O75694_K0824"
##              logFC se       df  t pval adjPval
## O75694_K0824    NA NA 5.561565 NA   NA      NA
## [1] "O75694_K0890"
##              logFC se       df  t pval adjPval
## O75694_K0890    NA NA 5.561565 NA   NA      NA
## [1] "O75694_K0902"
##                   logFC       se       df          t      pval adjPval
## O75694_K0902 -0.7680094 2.026458 9.437002 -0.3789911 0.7130815       1
## [1] "O75694_K0987"
##                    logFC        se       df          t      pval adjPval
## O75694_K0987 -0.07075939 0.4983178 9.585284 -0.1419965 0.8900228       1
## [1] "O75694_K1069"
##              logFC se       df  t pval adjPval
## O75694_K1069    NA NA 4.561565 NA   NA      NA
## [1] "O75694_K1126"
##                 logFC       se       df        t      pval adjPval
## O75694_K1126 2.708987 2.618607 10.43998 1.034515 0.3242647       1

2.1 Msqrob for MSstats summary

estimated ptm abundance -> rowData(peMSstatsSum[[“ptmNorm”]])\(msqrobModels\)P18124_K029 %>% getCoef() protein abundance -> summarized_ptm\(PROTEIN\)ProteinLevelData %>% filter(Protein == i) %>% pull(LogIntensities) ptm abundance -> assay(peMSstatsSum[[“ptm]]) of summarized_ptm\(PTM\)ProteinLevelData %>% filter(Protein == i) %>% pull(LogIntensities) normalised ptm abundance -> assay(peMSstatsSum[[“ptmNorm]])

## Plot significant ptm's from Combo vs Ctrl
ptm_list3 <- rowData(pe[["ptmMSstatsRel"]])$groupCombo %>% filter(adjPval <= 0.05) %>% rownames()
plots <- c()
for (i in ptm_list3){
  prot <- strsplit(i, "_")[[1]][1]

#Protein abundance
protein <- tibble(originalRUN, GROUP)
protein$FeatureType <- "Protein"
protein$Protein <- prot
tmp <- summarized_ptm$PROTEIN$ProteinLevelData %>% filter(Protein == prot) %>%
  select(c(LogIntensities, originalRUN))
missing_runs <- setdiff(originalRUN, tmp$originalRUN)
tmp2 <- tibble(originalRUN = missing_runs, LogIntensities = NA)
tmp3 <- rbind(tmp, tmp2) %>% arrange(originalRUN) %>% select(LogIntensities)
protein <- cbind(protein, tmp3)

#PTM abundance
ptm_df <- tibble(originalRUN, GROUP)
ptm_df$FeatureType <- "PTM"
ptm_df$Protein <- i
tmp <- summarized_ptm$PTM$ProteinLevelData %>% filter(Protein == i) %>% 
  select(c(LogIntensities, originalRUN))
missing_runs <- setdiff(originalRUN, tmp$originalRUN)
tmp2 <- tibble(originalRUN = missing_runs, LogIntensities = NA)
tmp3 <- rbind(tmp, tmp2) %>% arrange(originalRUN) %>% select(LogIntensities)
ptm_df <- cbind(ptm_df, tmp3)


#Normalised PTM abundance
ptm_df_norm <- assay(pe[["ptmMSstatsRel"]])[i,] %>% as.data.frame()
colnames(ptm_df_norm) <- "LogIntensities"
ptm_df_norm <- ptm_df_norm %>%
  mutate(Protein = i,
         FeatureType = "PTM - normalised",
         GROUP = sapply(strsplit(rownames(ptm_df_norm), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP)


#PTM estimated
Protein <- rep(i, nrow(ptm_df))
ptm_estimate <- tibble(Protein)
ptm_estimate$originalRUN <- ptm_df$originalRUN
ptm_estimate$GROUP <- ptm_df$GROUP
ptm_estimate$FeatureType <- "PTM_estimated"
ptm_estimate$LogIntensities <- NA

fixeffects <- rowData(pe[["ptmMSstatsRel"]])$msqrobModels[[i]] %>% getCoef
ptm_estimate[ptm_estimate$GROUP=="Ctrl",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]]
ptm_estimate[ptm_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="CCCP",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("CCCP", names(fixeffects))][1]
ptm_estimate[ptm_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))][1]


plot_df <- rbindlist(list(protein, ptm_df_norm, ptm_df, ptm_estimate), fill = TRUE)
plot_df <- plot_df %>% arrange(FeatureType)
plot_df$originalRUN <- forcats::fct_inorder(plot_df$originalRUN)
plot_points <- plot_df %>% filter(FeatureType != "PTM_estimated")

#plot_df[plot_df$FeatureType == 'Model'][['FeatureType']] <- "PTM Summarized"
#plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
    scale_colour_manual(values = c("PTM - normalised" = "lightgoldenrod", "Protein" = "skyblue3", 
                                 "PTM" = "seagreen3", "PTM_estimated" = "palevioletred2")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0)) +
  annotate("text", x = 2.5, y = 27, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 27, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 27, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 27, label = "USP30", size = 8) +
  ylim(-7, 27)

plots[[i]] <- p1
}
plots
## $O60361_K109
## Warning: Removed 8 row(s) containing missing values (geom_path).
## Warning: Removed 8 rows containing missing values (geom_point).

## 
## $P23396_K062

## 
## $P23396_K075

## 
## $P32969_K121

## 
## $P46781_K066

## 
## $P53621_K0825
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $P62736_K328
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $Q07020_K049

## 
## $Q07955_K138

## 
## $Q14683_K0536

## 
## $Q9Y277_K053
## Warning: Removed 2 rows containing missing values (geom_point).

2.1.1 For MSstats significant ptms

## Plot fourty ptm's from Combo vs Ctrl
originalRUN <- c("CCCP-B1T1", "CCCP-B1T2", "CCCP-B2T1", "CCCP-B2T2", "Combo-B1T1", 
                 "Combo-B1T2", "Combo-B2T1", "Combo-B2T2", "Ctrl-B1T1", "Ctrl-B1T2",   
                 "Ctrl-B2T1", "Ctrl-B2T2", "USP30_OE-B1T1", "USP30_OE-B1T2", 
                 "USP30_OE-B2T1", "USP30_OE-B2T2")
GROUP <- sapply(strsplit(originalRUN, "-"), function(x) x[1])
plots <- c()
for (i in ptm_list1){
  if (i %in% ptm_list3){print(paste(i, "also significant in msqrob"))}
  prot <- strsplit(i, "_")[[1]][1]

#Protein abundance
protein <- tibble(originalRUN, GROUP)
protein$FeatureType <- "Protein"
protein$Protein <- prot
tmp <- summarized_ptm$PROTEIN$ProteinLevelData %>% filter(Protein == prot) %>%
  select(c(LogIntensities, originalRUN))
missing_runs <- setdiff(originalRUN, tmp$originalRUN)
tmp2 <- tibble(originalRUN = missing_runs, LogIntensities = NA)
tmp3 <- rbind(tmp, tmp2) %>% arrange(originalRUN) %>% select(LogIntensities)
protein <- cbind(protein, tmp3)


#PTM abundance
ptm_df <- tibble(originalRUN, GROUP)
ptm_df$FeatureType <- "PTM"
ptm_df$Protein <- i
tmp <- summarized_ptm$PTM$ProteinLevelData %>% filter(Protein == i) %>% 
  select(c(LogIntensities, originalRUN))
missing_runs <- setdiff(originalRUN, tmp$originalRUN)
tmp2 <- tibble(originalRUN = missing_runs, LogIntensities = NA)
tmp3 <- rbind(tmp, tmp2) %>% arrange(originalRUN) %>% select(LogIntensities)
ptm_df <- cbind(ptm_df, tmp3)

#Normalised PTM abundance
if (!i %in% rownames(assay(pe[["ptmMSstatsRel"]]))){
  print(paste(i, "not in normalised PTM data"))
  plot_df <- rbindlist(list(protein, ptm_df), fill = TRUE)
  p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size =2) +
  geom_point(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("PTM - normalised" = "lightgoldenrod", "Protein" = "skyblue3", 
                                 "PTM" = "seagreen3", "PTM_estimated" = "palevioletred2")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = paste(i, "no normalisation possible"), x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0)) +
  annotate("text", x = 2.5, y = 27, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 27, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 27, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 27, label = "USP30", size = 8) +
  ylim(-7, 27)

plots[[i]] <- p1
next
}
ptm_df_norm <- assay(pe[["ptmMSstatsRel"]])[i,] %>% as.data.frame()
colnames(ptm_df_norm) <- "LogIntensities"
ptm_df_norm <- ptm_df_norm %>%
  mutate(Protein = i,
         FeatureType = "PTM - normalised",
         GROUP = sapply(strsplit(rownames(ptm_df_norm), "-"), function(x) x[1])) %>%
         rownames_to_column("originalRUN") %>%
         arrange(GROUP)


#PTM estimated
Protein <- rep(i, nrow(ptm_df))
ptm_estimate <- tibble(Protein)
ptm_estimate$originalRUN <- ptm_df$originalRUN
ptm_estimate$GROUP <- ptm_df$GROUP
ptm_estimate$FeatureType <- "PTM_estimated"
ptm_estimate$LogIntensities <- NA

if(rowData(pe[["ptmMSstatsRel"]])$msqrobModels[[i]] %>% getFitMethod() == "fitError"){
    print(paste(i, "resulted in a fitError"))
  plot_df <- rbindlist(list(protein, ptm_df, ptm_df_norm), fill = TRUE)
  p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size =2) +
  geom_point(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("PTM - normalised" = "lightgoldenrod", "Protein" = "skyblue3", 
                                 "PTM" = "seagreen3", "PTM_estimated" = "palevioletred2")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = paste(i, "fitError"), x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0)) +
  annotate("text", x = 2.5, y = 27, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 27, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 27, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 27, label = "USP30", size = 8) +
  ylim(-7, 27)

plots[[i]] <- p1
  next
}
fixeffects <- rowData(pe[["ptmMSstatsRel"]])$msqrobModels[[i]] %>% getCoef
try(ptm_estimate[ptm_estimate$GROUP=="Ctrl",]$LogIntensities <- 
                                                    fixeffects[["(Intercept)"]])
try(ptm_estimate[ptm_estimate$GROUP=="Combo",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("Combo", names(fixeffects))][1])
try(ptm_estimate[ptm_estimate$GROUP=="CCCP",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("CCCP", names(fixeffects))][1])
try(ptm_estimate[ptm_estimate$GROUP=="USP30_OE",]$LogIntensities <- 
   fixeffects[["(Intercept)"]] + fixeffects[grepl("USP30_OE", names(fixeffects))][1])


plot_df <- rbindlist(list(protein, ptm_df_norm, ptm_df, ptm_estimate), fill = TRUE)
plot_df <- plot_df %>% arrange(FeatureType)
plot_df$originalRUN <- forcats::fct_inorder(plot_df$originalRUN)
plot_points <- plot_df %>% filter(FeatureType != "PTM_estimated")

#plot_df[plot_df$FeatureType == 'Model'][['FeatureType']] <- "PTM Summarized"
#plot_df[plot_df$FeatureType == 'Peptide'][['FeatureType']] <- "PTM Feature"

p1 <- plot_df %>% ggplot() +
  geom_line(aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = originalRUN, y = LogIntensities , group = FeatureType, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(4.5, 8.5, 12.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("PTM - normalised" = "lightgoldenrod", "Protein" = "skyblue3", 
                                 "PTM" = "seagreen3", "PTM_estimated" = "palevioletred2")) +
  #scale_size_manual(values = c(1, 2)) +
  labs(title = i, x = "BioReplicate", y = "LogIntensity") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 16),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=10),
        axis.title.y = element_text(size = 22),
        axis.title.x = element_text(size = 22),
        title = element_text(size = 22),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0)) +
  annotate("text", x = 2.5, y = 30, label = "CCCP", size = 8) +
  annotate("text", x = 6.5, y = 30, label = "Combo", size = 8) +
  annotate("text", x = 10.5, y = 30, label = "Ctrl", size = 8) +
  annotate("text", x = 14.5, y = 30, label = "USP30", size = 8) +
  ylim(-10, 30)

plots[[i]] <- p1
}
## [1] "A0FGR9_K608 resulted in a fitError"
## [1] "B2RB47_K073 resulted in a fitError"
## [1] "O14980_K0686 resulted in a fitError"
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## [1] "O60341_K492 resulted in a fitError"
## [1] "O60361_K109 also significant in msqrob"
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## Error in fixeffects[["(Intercept)"]] : subscript out of bounds
## [1] "O60749_K516 resulted in a fitError"
## [1] "O75131_K158 resulted in a fitError"
## [1] "O75150_K440 resulted in a fitError"
## [1] "O75694_K0824 resulted in a fitError"
## [1] "O75694_K1069 resulted in a fitError"
plots
## $A0FGR9_K608
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 32 rows containing missing values (geom_point).

## 
## $B2RB47_K073
## Warning: Removed 28 row(s) containing missing values (geom_path).
## Warning: Removed 36 rows containing missing values (geom_point).

## 
## $O00154_K205
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 17 rows containing missing values (geom_point).

## 
## $O00159_K0578
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 12 rows containing missing values (geom_point).

## 
## $O00170_K215
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O00232_K262
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Removed 18 rows containing missing values (geom_point).

## 
## $O00267_K0627
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $O00410_K0806

## 
## $O14972_K103
## Warning: Removed 5 row(s) containing missing values (geom_path).
## Warning: Removed 17 rows containing missing values (geom_point).

## 
## $O14980_K0686
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O15372_K274
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 20 rows containing missing values (geom_point).

## 
## $O43175_K289
## Warning: Removed 4 rows containing missing values (geom_point).

## 
## $O43670_K100
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $O43847_K0993
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 26 rows containing missing values (geom_point).

## 
## $O60260_K076
## Warning: Removed 2 rows containing missing values (geom_point).

## 
## $O60260_K220

## 
## $O60260_K369

## 
## $O60260_K408

## 
## $O60260_K435
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $O60341_K492
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 34 rows containing missing values (geom_point).

## 
## $O60361_K034
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O60361_K041

## 
## $O60361_K070
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $O60361_K109

## 
## $O60361_K113
## Warning: Removed 30 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O60506_K336
## Warning: Removed 4 rows containing missing values (geom_point).

## 
## $O60749_K218
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 17 rows containing missing values (geom_point).

## 
## $O60749_K516
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 32 rows containing missing values (geom_point).

## 
## $O60832_K433
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 17 rows containing missing values (geom_point).

## 
## $O60888_K082
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O75131_K158
## Warning: Removed 24 row(s) containing missing values (geom_path).
## Warning: Removed 35 rows containing missing values (geom_point).

## 
## $O75150_K440
## Warning: Removed 24 row(s) containing missing values (geom_path).
## Removed 35 rows containing missing values (geom_point).

## 
## $O75400_K669
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

## 
## $O75694_K0740
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Removed 16 rows containing missing values (geom_point).

## 
## $O75694_K0824
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 32 rows containing missing values (geom_point).

## 
## $O75694_K0890
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 24 rows containing missing values (geom_point).

## 
## $O75694_K0902
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 18 rows containing missing values (geom_point).

## 
## $O75694_K0987
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Removed 18 rows containing missing values (geom_point).

## 
## $O75694_K1069
## Warning: Removed 20 row(s) containing missing values (geom_path).
## Warning: Removed 33 rows containing missing values (geom_point).

## 
## $O75694_K1126
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 16 rows containing missing values (geom_point).

for (i in ptm_list1){
  print(i)
  print(rowData(pe[["ptmMSstatsRel"]])$groupCombo[i,])
  }
## [1] "A0FGR9_K608"
##             logFC se df  t pval adjPval
## A0FGR9_K608    NA NA NA NA   NA      NA
## [1] "B2RB47_K073"
##             logFC se df  t pval adjPval
## B2RB47_K073    NA NA NA NA   NA      NA
## [1] "O00154_K205"
##             logFC se       df  t pval adjPval
## O00154_K205    NA NA 6.115833 NA   NA      NA
## [1] "O00159_K0578"
##              logFC se       df  t pval adjPval
## O00159_K0578    NA NA 6.993305 NA   NA      NA
## [1] "O00170_K215"
##             logFC se       df  t pval adjPval
## O00170_K215    NA NA 5.115833 NA   NA      NA
## [1] "O00232_K262"
##             logFC se       df  t pval adjPval
## O00232_K262    NA NA 5.115833 NA   NA      NA
## [1] "O00267_K0627"
##              logFC se       df  t pval adjPval
## O00267_K0627    NA NA 6.115833 NA   NA      NA
## [1] "O00410_K0806"
##                 logFC       se       df        t       pval   adjPval
## O00410_K0806 3.075823 1.418033 11.07609 2.169077 0.05269811 0.7011021
## [1] "O14972_K103"
##             logFC se       df  t pval adjPval
## O14972_K103    NA NA 6.115833 NA   NA      NA
## [1] "O14980_K0686"
##              logFC se df  t pval adjPval
## O14980_K0686    NA NA NA NA   NA      NA
## [1] "O15372_K274"
##             logFC se df  t pval adjPval
## O15372_K274    NA NA NA NA   NA      NA
## [1] "O43175_K289"
##             logFC se      df  t pval adjPval
## O43175_K289    NA NA 9.88883 NA   NA      NA
## [1] "O43670_K100"
##             logFC se       df  t pval adjPval
## O43670_K100    NA NA 6.115833 NA   NA      NA
## [1] "O43847_K0993"
##              logFC se       df  t pval adjPval
## O43847_K0993    NA NA 5.115833 NA   NA      NA
## [1] "O60260_K076"
##                logFC       se       df        t      pval   adjPval
## O60260_K076 2.947903 1.078911 10.05118 2.732297 0.0210186 0.5439243
## [1] "O60260_K220"
##                logFC        se       df        t        pval   adjPval
## O60260_K220 2.945495 0.8255802 11.13382 3.567788 0.004331355 0.2309399
## [1] "O60260_K369"
##                logFC        se       df       t        pval  adjPval
## O60260_K369 1.211412 0.2863608 12.50321 4.23037 0.001068061 0.104403
## [1] "O60260_K408"
##                logFC        se       df        t        pval   adjPval
## O60260_K408 3.212302 0.8237631 11.05165 3.899546 0.002457055 0.1742382
## [1] "O60260_K435"
##             logFC se       df  t pval adjPval
## O60260_K435    NA NA 6.115833 NA   NA      NA
## [1] "O60341_K492"
##             logFC se df  t pval adjPval
## O60341_K492    NA NA NA NA   NA      NA
## [1] "O60361_K034"
##             logFC se       df  t pval adjPval
## O60361_K034    NA NA 5.115833 NA   NA      NA
## [1] "O60361_K041"
##                logFC       se       df        t      pval   adjPval
## O60361_K041 1.485787 1.261051 11.04014 1.178213 0.2634839 0.9996807
## [1] "O60361_K070"
##             logFC se       df  t pval adjPval
## O60361_K070    NA NA 6.115833 NA   NA      NA
## [1] "O60361_K109"
##                logFC        se       df        t         pval    adjPval
## O60361_K109 2.924282 0.5490288 11.26627 5.326281 0.0002235512 0.02622256
## [1] "O60361_K113"
##             logFC se df  t pval adjPval
## O60361_K113    NA NA NA NA   NA      NA
## [1] "O60506_K336"
##                logFC       se       df        t      pval   adjPval
## O60506_K336 5.149196 3.801191 9.167772 1.354627 0.2079758 0.9996807
## [1] "O60749_K218"
##             logFC se       df  t pval adjPval
## O60749_K218    NA NA 6.115833 NA   NA      NA
## [1] "O60749_K516"
##             logFC se df  t pval adjPval
## O60749_K516    NA NA NA NA   NA      NA
## [1] "O60832_K433"
##             logFC se       df  t pval adjPval
## O60832_K433    NA NA 6.115833 NA   NA      NA
## [1] "O60888_K082"
##             logFC se       df  t pval adjPval
## O60888_K082    NA NA 5.115833 NA   NA      NA
## [1] "O75131_K158"
##             logFC se df  t pval adjPval
## O75131_K158    NA NA NA NA   NA      NA
## [1] "O75150_K440"
##             logFC se df  t pval adjPval
## O75150_K440    NA NA NA NA   NA      NA
## [1] "O75400_K669"
##             logFC se       df  t pval adjPval
## O75400_K669    NA NA 6.115833 NA   NA      NA
## [1] "O75694_K0740"
##              logFC se       df  t pval adjPval
## O75694_K0740    NA NA 6.115833 NA   NA      NA
## [1] "O75694_K0824"
##              logFC se df  t pval adjPval
## O75694_K0824    NA NA NA NA   NA      NA
## [1] "O75694_K0890"
##              logFC se       df  t pval adjPval
## O75694_K0890    NA NA 6.115833 NA   NA      NA
## [1] "O75694_K0902"
##              logFC se       df  t pval adjPval
## O75694_K0902    NA NA 5.115833 NA   NA      NA
## [1] "O75694_K0987"
##              logFC se       df  t pval adjPval
## O75694_K0987    NA NA 5.115833 NA   NA      NA
## [1] "O75694_K1069"
##              logFC se df  t pval adjPval
## O75694_K1069    NA NA NA NA   NA      NA
## [1] "O75694_K1126"
##              logFC se       df  t pval adjPval
## O75694_K1126    NA NA 6.115833 NA   NA      NA
LS0tDQp0aXRsZTogIlViaXF1aXRpbmF0aW9uIHZpc3VhbGlzYXRpb24iDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdGhlbWU6IGNvc21vDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6ICc0Jw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KE1Tc3RhdHNQVE0pDQpsaWJyYXJ5KGxtZTQpDQpsaWJyYXJ5KG1zcXJvYjIpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpgYGANCg0KDQpMb2FkIGluIGFsbCBkYXRhDQoNCmBgYHtyfQ0KZGlyZWN0b3J5ID0gIkM6L1VzZXJzL05pbmEvT25lRHJpdmUgLSBVR2VudC9Eb2N1bWVudGVuL0RvY3RvcmFhdC9tc3Fyb2JQVE0gcGFwZXIvYmlvbG9naWNhbCB1YmlxdWl0aW4gZGF0YXNldC8iDQojTVNTdGF0cyBkYXRhDQpsb2FkKHBhc3RlMChkaXJlY3RvcnksICJNU3N0YXRzU3VtbWFyaXplZERhdGEuUkRhdGEiKSkNCmxvYWQocGFzdGUwKGRpcmVjdG9yeSwgIk1Tc3RhdHNNb2RlbC5yZGEiKSkNCiNNc3Fyb2INCmxvYWQoInBlX3ViaXF1aXRpbl9tc3Fyb2IucmRhIikNCmBgYA0KDQoNCiMgTVNzdGF0cw0KDQplc3RpbWF0ZWQgcHRtIGFidW5kYW5jZSAtPmZpeGVmKG1vZGVsX3B0bSRNb2RlbC5EZXRhaWxzJFBUTVtbMTAwXV0pIA0KcHJvdGVpbiBhYnVuZGFuY2UgKGZvciBwcm90ZWluIGkpIC0+IHN1bW1hcml6ZWRfcHRtJFBST1RFSU4kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gaSkgJT4lIHB1bGwoTG9nSW50ZW5zaXRpZXMpDQpwdG0gYWJ1bmRhbmNlIChmb3IgcHRtIGkpIC0+IHN1bW1hcml6ZWRfcHRtJFBUTSRQcm90ZWluTGV2ZWxEYXRhICU+JSBmaWx0ZXIoUHJvdGVpbiA9PSBpKSAlPiUgcHVsbChMb2dJbnRlbnNpdGllcykNCm5vcm1hbGlzZWQgcHRtIGFidW5kYW5jZSAtPiAgbW9kZWxfcHRtJE1vZGVsLkRldGFpbHMkUFRNW1sxMDBdXSAtIG1vZGVsX3B0bSRNb2RlbC5EZXRhaWxzJFBST1RFSU5bWzEwMF1dDQoNCkF0IHRoZSBtb21lbnQsIG9ubHkgaW4gdGhlIEdpdEh1YiB2ZXJzaW9uLCBhIGRldGFpbGVkIG1vZGVsIGdldHMgb3V0cHV0dGVkIHdpdGggaW5mbyBvbiB0aGUNCmVzdGltYXRlcyBvbiBldmVyeXRoaW5nLCBzbyBJIHVzZWQgdGhhdCBoZXJlDQoNCg0KYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEwfQ0Kb3JpZ2luYWxSVU4gPC0gYygiQ0NDUC1CMVQxIiwgIkNDQ1AtQjFUMiIsICJDQ0NQLUIyVDEiLCAiQ0NDUC1CMlQyIiwgIkNvbWJvLUIxVDEiLCANCiAgICAgICAgICAgICAgICAgIkNvbWJvLUIxVDIiLCAiQ29tYm8tQjJUMSIsICJDb21iby1CMlQyIiwgIkN0cmwtQjFUMSIsICJDdHJsLUIxVDIiLCAgIA0KICAgICAgICAgICAgICAgICAiQ3RybC1CMlQxIiwgIkN0cmwtQjJUMiIsICJVU1AzMF9PRS1CMVQxIiwgIlVTUDMwX09FLUIxVDIiLCANCiAgICAgICAgICAgICAgICAgIlVTUDMwX09FLUIyVDEiLCAiVVNQMzBfT0UtQjJUMiIpDQpHUk9VUCA8LSBzYXBwbHkoc3Ryc3BsaXQob3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pDQojIyBQbG90IGZvdXJ0eSBwdG0ncyBmcm9tIENvbWJvIHZzIEN0cmwNCnB0bV9saXN0MSA8LSBtb2RlbF9wdG0kQURKVVNURUQuTW9kZWwgJT4lIGZpbHRlcihMYWJlbCA9PSAiQ29tYm8gdnMgQ3RybCIpICU+JSBmaWx0ZXIoYWRqLnB2YWx1ZSA8PSAwLjA1KSAlPiUgaGVhZCg0MCkgJT4lIHB1bGwoUHJvdGVpbikNCmFsbF9wdG1zIDwtIG1vZGVsX3B0bSRQVE0uTW9kZWwgJT4lIHB1bGwoUHJvdGVpbikgJT4lIHVuaXF1ZSgpDQphbGxfcHJvdGVpbnMgPC0gbW9kZWxfcHRtJFBST1RFSU4uTW9kZWwgJT4lIHB1bGwoUHJvdGVpbikgJT4lIHVuaXF1ZSgpDQphZGp1c3RlZF9wdG1zIDwtIG1vZGVsX3B0bSRBREpVU1RFRC5Nb2RlbCAlPiUgcHVsbChQcm90ZWluKSAlPiUgdW5pcXVlKCkNCnBsb3RzIDwtIGMoKQ0KZm9yIChpIGluIHB0bV9saXN0MSl7DQogIHByaW50KGkpDQogIHByb3QgPC0gc3Ryc3BsaXQoaSwgIl8iKVtbMV1dWzFdDQogIGluZGV4IDwtIHdoaWNoKGFsbF9wdG1zID09IGkpDQogIGluZGV4X3Byb3QgPC0gd2hpY2goYWxsX3Byb3RlaW5zID09IHByb3QpDQogIGluZGV4X2FkanVzdGVkIDwtIHdoaWNoKGFkanVzdGVkX3B0bXMgPT0gaSkNCiNQcm90ZWluIGFidW5kYW5jZQ0KcHJvdGVpbiA8LSB0aWJibGUob3JpZ2luYWxSVU4sIEdST1VQKQ0KcHJvdGVpbiRGZWF0dXJlVHlwZSA8LSAiUHJvdGVpbiINCnByb3RlaW4kUHJvdGVpbiA8LSBwcm90DQp0bXAgPC0gc3VtbWFyaXplZF9wdG0kUFJPVEVJTiRQcm90ZWluTGV2ZWxEYXRhICU+JSBmaWx0ZXIoUHJvdGVpbiA9PSBwcm90KSAlPiUNCiAgc2VsZWN0KGMoTG9nSW50ZW5zaXRpZXMsIG9yaWdpbmFsUlVOKSkNCm1pc3NpbmdfcnVucyA8LSBzZXRkaWZmKG9yaWdpbmFsUlVOLCB0bXAkb3JpZ2luYWxSVU4pDQp0bXAyIDwtIHRpYmJsZShvcmlnaW5hbFJVTiA9IG1pc3NpbmdfcnVucywgTG9nSW50ZW5zaXRpZXMgPSBOQSkNCnRtcDMgPC0gcmJpbmQodG1wLCB0bXAyKSAlPiUgYXJyYW5nZShvcmlnaW5hbFJVTikgJT4lIHNlbGVjdChMb2dJbnRlbnNpdGllcykNCnByb3RlaW4gPC0gY2JpbmQocHJvdGVpbiwgdG1wMykNCg0KI1BUTSBhYnVuZGFuY2UNCnB0bV9kZiA8LSBzdW1tYXJpemVkX3B0bSRQVE0kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gaSkNCnB0bV9kZiRBYnVuZGFuY2UgPC0gcHRtX2RmJExvZ0ludGVuc2l0aWVzDQpwdG1fZGYkRmVhdHVyZVR5cGUgPC0gIlBUTSINCnB0bV9kZiA8LSBwdG1fZGYgJT4lIHNlbGVjdChjKCJQcm90ZWluIiwgIkxvZ0ludGVuc2l0aWVzIiwgIm9yaWdpbmFsUlVOIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHUk9VUCIsICJGZWF0dXJlVHlwZSIpKQ0KDQojUFRNIGVzdGltYXRlZCAobWFhciBub2cgbmlldCBhZGp1c3RlZCkNClByb3RlaW4gPC0gcmVwKGksIGxlbmd0aChvcmlnaW5hbFJVTikpDQpwdG1fZXN0aW1hdGUgPC0gdGliYmxlKFByb3RlaW4pDQpwdG1fZXN0aW1hdGUkb3JpZ2luYWxSVU4gPC0gb3JpZ2luYWxSVU4NCnB0bV9lc3RpbWF0ZSRHUk9VUCA8LSBHUk9VUA0KcHRtX2VzdGltYXRlJEZlYXR1cmVUeXBlIDwtICJQVE1fZXN0aW1hdGVkIg0KcHRtX2VzdGltYXRlJExvZ0ludGVuc2l0aWVzIDwtIE5BDQoNCiNDaGVjayB0aGF0IG1vZGVsIGVzdGltYXRlcyBhcmUgZGVmaW5pdGVseSBmcm9tIHRoYXQgUFRNDQppZiAoY2xhc3MobW9kZWxfcHRtJE1vZGVsLkRldGFpbHMkUFRNW1tpbmRleF1dKSA9PSAibG0iKXtwcmludChpKQ0KICB9ZWxzZXsNCnByaW50KGFsbCgNCiAgc3VtbWFyaXplZF9wdG0kUFRNJFByb3RlaW5MZXZlbERhdGEgJT4lIGZpbHRlcihQcm90ZWluID09IGkpICU+JSBwdWxsKExvZ0ludGVuc2l0aWVzKSA9PQ0KICAgIGdldE1FKG1vZGVsX3B0bSRNb2RlbC5EZXRhaWxzJFBUTVtbaW5kZXhdXSwgInkiKQ0KKSl9DQoNCmlmIChjbGFzcyhtb2RlbF9wdG0kTW9kZWwuRGV0YWlscyRQVE1bW2luZGV4XV0pID09ICJsbSIpew0KZml4ZWZmZWN0cyA8LSBtb2RlbF9wdG0kTW9kZWwuRGV0YWlscyRQVE1bW2luZGV4XV0kY29lZmZpY2llbnRzDQp9IGVsc2Uge2ZpeGVmZmVjdHMgPC0gZml4ZWYobW9kZWxfcHRtJE1vZGVsLkRldGFpbHMkUFRNW1tpbmRleF1dKX0gDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ0NDUCIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0NCnRyeShwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ29tYm8iLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJDb21ibyIsIG5hbWVzKGZpeGVmZmVjdHMpKV0pDQp0cnkocHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRHUk9VUD09IkN0cmwiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJDdHJsIiwgbmFtZXMoZml4ZWZmZWN0cykpXSkNCnRyeShwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iVVNQMzBfT0UiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJVU1AzMF9PRSIsIG5hbWVzKGZpeGVmZmVjdHMpKV0pDQoNCiNQcm90ZWluIGVzdGltYXRlZCAobWFhciBub2cgbmlldCBhZGp1c3RlZCkNClByb3RlaW4gPC0gcmVwKHByb3QsIGxlbmd0aChvcmlnaW5hbFJVTikpDQpwcm90X2VzdGltYXRlIDwtIHRpYmJsZShQcm90ZWluKQ0KcHJvdF9lc3RpbWF0ZSRvcmlnaW5hbFJVTiA8LSBvcmlnaW5hbFJVTg0KcHJvdF9lc3RpbWF0ZSRHUk9VUCA8LSBHUk9VUA0KcHJvdF9lc3RpbWF0ZSRGZWF0dXJlVHlwZSA8LSAiUHJvdGVpbl9lc3RpbWF0ZWQiDQpwcm90X2VzdGltYXRlJExvZ0ludGVuc2l0aWVzIDwtIE5BDQoNCiNDaGVjayB0aGF0IG1vZGVsIGVzdGltYXRlcyBhcmUgZGVmaW5pdGVseSBmcm9tIHRoYXQgUFRNDQppZiAoY2xhc3MobW9kZWxfcHRtJE1vZGVsLkRldGFpbHMkUFJPVEVJTltbaW5kZXhfcHJvdF1dKSA9PSAibG1lck1vZCIpew0KICBwcmludChhbGwoDQogIHN1bW1hcml6ZWRfcHRtJFBST1RFSU4kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gcHJvdCkgJT4lIHB1bGwoTG9nSW50ZW5zaXRpZXMpID09DQogICAgZ2V0TUUobW9kZWxfcHRtJE1vZGVsLkRldGFpbHMkUFJPVEVJTltbaW5kZXhfcHJvdF1dLCAieSIpKSkNCn0NCg0KaWYgKGNsYXNzKG1vZGVsX3B0bSRNb2RlbC5EZXRhaWxzJFBST1RFSU5bW2luZGV4X3Byb3RdXSkgPT0gImxtIil7DQpmaXhlZmZlY3RzIDwtIG1vZGVsX3B0bSRNb2RlbC5EZXRhaWxzJFBST1RFSU5bW2luZGV4X3Byb3RdXSRjb2VmZmljaWVudHMNCn0gZWxzZSB7Zml4ZWZmZWN0cyA8LSBmaXhlZihtb2RlbF9wdG0kTW9kZWwuRGV0YWlscyRQUk9URUlOW1tpbmRleF9wcm90XV0pfSANCnByb3RfZXN0aW1hdGVbcHJvdF9lc3RpbWF0ZSRHUk9VUD09IkNDQ1AiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dDQp0cnkocHJvdF9lc3RpbWF0ZVtwcm90X2VzdGltYXRlJEdST1VQPT0iQ29tYm8iLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJDb21ibyIsIG5hbWVzKGZpeGVmZmVjdHMpKV0pDQp0cnkocHJvdF9lc3RpbWF0ZVtwcm90X2VzdGltYXRlJEdST1VQPT0iQ3RybCIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIkN0cmwiLCBuYW1lcyhmaXhlZmZlY3RzKSldKQ0KdHJ5KHByb3RfZXN0aW1hdGVbcHJvdF9lc3RpbWF0ZSRHUk9VUD09IlVTUDMwX09FIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tncmVwbCgiVVNQMzBfT0UiLCBuYW1lcyhmaXhlZmZlY3RzKSldKQ0KDQojUFRNIG5vcm1hbGlzZWQNClByb3RlaW4gPC0gcmVwKGksIGxlbmd0aChvcmlnaW5hbFJVTikpDQpwdG1fbm9ybSA8LSB0aWJibGUoUHJvdGVpbikNCnB0bV9ub3JtJG9yaWdpbmFsUlVOIDwtIG9yaWdpbmFsUlVODQpwdG1fbm9ybSRHUk9VUCA8LSBHUk9VUA0KcHRtX25vcm0kRmVhdHVyZVR5cGUgPC0gIlBUTV9ub3JtYWxpc2VkIg0KcHRtX25vcm0kTG9nSW50ZW5zaXRpZXMgPC0gcHRtX2VzdGltYXRlJExvZ0ludGVuc2l0aWVzIC0gcHJvdF9lc3RpbWF0ZSRMb2dJbnRlbnNpdGllcw0KDQoNCnBsb3RfZGYgPC0gcmJpbmRsaXN0KGxpc3QocHJvdGVpbiwgcHRtX2RmLCBwdG1fZXN0aW1hdGUsIHByb3RfZXN0aW1hdGUsIHB0bV9ub3JtKSwgZmlsbCA9IFRSVUUpDQpwbG90X3BvaW50cyA8LSByYmluZGxpc3QobGlzdChwcm90ZWluLCBwdG1fZGYpLCBmaWxsID0gVFJVRSkNCg0KI3Bsb3RfZGZbcGxvdF9kZiRGZWF0dXJlVHlwZSA9PSAnTW9kZWwnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gU3VtbWFyaXplZCINCiNwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ1BlcHRpZGUnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gRmVhdHVyZSINCg0KcDEgPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBGZWF0dXJlVHlwZSwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gcGxvdF9wb2ludHMsIGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gRmVhdHVyZVR5cGUsIGNvbG9yID0gRmVhdHVyZVR5cGUpLCBzaXplID0gNSkgKw0KICBnZW9tX3ZsaW5lKGRhdGE9ZGF0YS5mcmFtZSh4ID0gYyg0LjUsIDguNSwgMTIuNSkpLA0KICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0PWFzLm51bWVyaWMoeCkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJQVE0iID0gInBhbGV2aW9sZXRyZWQxIiwgIlBUTV9lc3RpbWF0ZWQiID0gImRlZXBwaW5rNCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHJvdGVpbiIgPSAicGFsZWdyZWVuMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb3RlaW5fZXN0aW1hdGVkIiA9ICJzZWFncmVlbjQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBUTV9ub3JtYWxpc2VkIiA9ICJnb2xkZW5yb2QyIikpICsNCiAgI3NjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMikpICsNCiAgbGFicyh0aXRsZSA9IGksIHggPSAiQmlvUmVwbGljYXRlIiwgeSA9ICJMb2dJbnRlbnNpdHkiKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdD0xLCBzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMS41KSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9ICBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjA1KSkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLjUsIHkgPSAzMCwgbGFiZWwgPSAiQ0NDUCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDYuNSwgeSA9IDMwLCBsYWJlbCA9ICJDb21ibyIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEwLjUsIHkgPSAzMCwgbGFiZWwgPSAiQ3RybCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE0LjUsIHkgPSAzMCwgbGFiZWwgPSAiVVNQMzAiLCBzaXplID0gOCkgKw0KICB5bGltKC02LCAzMCkNCg0KcGxvdHNbW2ldXSA8LSBwMQ0KfQ0KcGxvdHMNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX3B0bSRBREpVU1RFRC5Nb2RlbCAlPiUgZmlsdGVyKFByb3RlaW4gPT0gIk82MDI2MF9LMzY5IiwgTGFiZWwgPT0gIkNvbWJvIHZzIEN0cmwiKQ0KYGBgDQoNCg0KIyBNc3Fyb2INCg0KZXN0aW1hdGVkIHB0bSBhYnVuZGFuY2UgLT4gcm93RGF0YShwZVtbInB0bVJlbCJdXSkkbXNxcm9iTW9kZWxzJFAxODEyNF9LMDI5ICU+JSBnZXRDb2VmKCkNCnByb3RlaW4gYWJ1bmRhbmNlIC0+IGFzc2F5KHBlW1sicHJvdGVpblJvYnVzdCJdXSkNCnB0bSBhYnVuZGFuY2UgLT4gdGhpcyBJIGRvIG5vdCBoYXZlLCBpcyBhbHJlYWR5IG5vcm1hbGlzZWQNCm5vcm1hbGlzZWQgcHRtIGFidW5kYW5jZSAtPiBhc3NheShwZVtbInB0bVJlbCJdXSkNCg0KDQpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQojIyBQbG90IHB0bSdzIGZyb20gQ29tYm8gdnMgQ3RybA0KcHRtX2xpc3QyIDwtIHJvd0RhdGEocGVbWyJwdG1SZWwiXV0pJGdyb3VwQ29tYm8gJT4lIGZpbHRlcihhZGpQdmFsIDw9IDAuMDUpICU+JSByb3duYW1lcygpDQpwbG90cyA8LSBjKCkNCmZvciAoaSBpbiBwdG1fbGlzdDIpew0KICBwcmludChpKQ0KICBwcm90IDwtIHN0cnNwbGl0KGksICJfIilbWzFdXVsxXQ0KDQojUHJvdGVpbiBhYnVuZGFuY2UNCnByb3RlaW4gPC0gYXNzYXkocGVbWyJwcm90ZWluUmF3Il1dKVtwcm90LF0gJT4lIGFzLmRhdGEuZnJhbWUoKSANCmNvbG5hbWVzKHByb3RlaW4pIDwtICJMb2dJbnRlbnNpdGllcyINCnByb3RlaW4gPC0gcHJvdGVpbiAlPiUNCiAgbXV0YXRlKFByb3RlaW4gPSBwcm90LA0KICAgICAgICAgRmVhdHVyZVR5cGUgPSAiUHJvdGVpbiIsDQogICAgICAgICBHUk9VUCA9IHNhcHBseShzdHJzcGxpdChyb3duYW1lcyhwcm90ZWluKSwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSkpICU+JQ0KICAgICAgICAgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnaW5hbFJVTiIpICU+JQ0KICAgICAgICAgYXJyYW5nZShHUk9VUCwgb3JpZ2luYWxSVU4pDQoNCiNQZXB0aWRvZm9ybSBhYnVuZGFuY2UNCnBlcGZvcm1zIDwtIHJvd0RhdGEocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgZmlsdGVyKHB0bSA9PSBpKSAlPiUgcm93bmFtZXMNCnBlcGZvcm0gPC0gYXNzYXkocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSlbcGVwZm9ybXMsXSAlPiUgYXMuZGF0YS5mcmFtZSgpDQppZiAobGVuZ3RoKHBlcGZvcm1zKT09MCkge25leHR9DQppZiAobGVuZ3RoKHBlcGZvcm1zKT4xKXsNCiAgcGVwZm9ybSA8LSBwZXBmb3JtICU+JSByb3duYW1lc190b19jb2x1bW4oIlByb3RlaW4iKSAlPiUgDQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb2xuYW1lcyhwZXBmb3JtKSwgbmFtZXNfdG8gPSAib3JpZ2luYWxSVU4iLA0KICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiTG9nSW50ZW5zaXRpZXMiKSANCiAgcGVwZm9ybSRHUk9VUCA8LSBzYXBwbHkoc3Ryc3BsaXQocGVwZm9ybSRvcmlnaW5hbFJVTiwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSkNCiAgcGVwZm9ybSA8LSBwZXBmb3JtICU+JSBhcnJhbmdlKEdST1VQLCBvcmlnaW5hbFJVTikNCn0gZWxzZSB7Y29sbmFtZXMocGVwZm9ybSkgPC0gIkxvZ0ludGVuc2l0aWVzIg0KICAgICAgICBwZXBmb3JtIDwtIHBlcGZvcm0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigib3JpZ2luYWxSVU4iKSANCiAgICAgICAgcGVwZm9ybSA8LSBwZXBmb3JtICU+JSBtdXRhdGUoR1JPVVAgPSANCiAgICAgICAgICAgICAgICAgICAgc2FwcGx5KHN0cnNwbGl0KHBlcGZvcm0kb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pLA0KICAgICAgICAgICAgICAgICAgICBQcm90ZWluID0gcGVwZm9ybXNbMV0pICU+JQ0KICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoR1JPVVAsIG9yaWdpbmFsUlVOKQ0KICAgICAgICB9DQpwZXBmb3JtIDwtIHBlcGZvcm0gJT4lDQogIG11dGF0ZShGZWF0dXJlVHlwZSA9ICJQZXB0aWRvZm9ybSIpDQojcGVwZm9ybSA8LSBzZWxlY3QoLWMoInBlcGZvcm0iKSkNCnBlcGZvcm0kb3JpZ2luYWxSVU4gPC0gZm9yY2F0czo6ZmN0X2lub3JkZXIocGVwZm9ybSRvcmlnaW5hbFJVTikNCg0KI1BlcHRpZG9mb3JtIGFidW5kYW5jZSAtIG5vcm1hbGlzZWQNCnBlcGZvcm1zIDwtIHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgICBmaWx0ZXIocHRtID09IGkpICU+JSByb3duYW1lcw0KcGVwZm9ybV9ub3JtIDwtIGFzc2F5KHBlW1sicGVwZm9ybVJlbCJdXSlbcGVwZm9ybXMsXSAlPiUgYXMuZGF0YS5mcmFtZSgpDQppZiAobGVuZ3RoKHBlcGZvcm1zKT4xKXsNCiAgcGVwZm9ybV9ub3JtIDwtIHBlcGZvcm1fbm9ybSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJQcm90ZWluIikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gY29sbmFtZXMocGVwZm9ybV9ub3JtKSwgbmFtZXNfdG8gPSAib3JpZ2luYWxSVU4iLA0KICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiTG9nSW50ZW5zaXRpZXMiKSANCiAgcGVwZm9ybV9ub3JtJEdST1VQIDwtIHNhcHBseShzdHJzcGxpdChwZXBmb3JtX25vcm0kb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pDQogIHBlcGZvcm1fbm9ybSA8LSBwZXBmb3JtX25vcm0gJT4lIGFycmFuZ2UoR1JPVVAsIG9yaWdpbmFsUlVOKSAlPiUNCiAgICBtdXRhdGUoUHJvdGVpbiA9IHBhc3RlKFByb3RlaW4sIm5vcm0iKSkNCn0gZWxzZSB7Y29sbmFtZXMocGVwZm9ybV9ub3JtKSA8LSAiTG9nSW50ZW5zaXRpZXMiDQogICAgICAgIHBlcGZvcm1fbm9ybSA8LSBwZXBmb3JtX25vcm0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigib3JpZ2luYWxSVU4iKSANCiAgICAgICAgcGVwZm9ybV9ub3JtIDwtIHBlcGZvcm1fbm9ybSAlPiUgbXV0YXRlKEdST1VQID0gDQogICAgICAgICAgICAgICAgICAgIHNhcHBseShzdHJzcGxpdChwZXBmb3JtX25vcm0kb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pLA0KICAgICAgICAgICAgICAgICAgICBQcm90ZWluID0gcGFzdGUocGVwZm9ybXNbMV0sIm5vcm0iKSkgJT4lDQogICAgICAgICAgICAgICAgICAgYXJyYW5nZShHUk9VUCwgb3JpZ2luYWxSVU4pDQogICAgICAgIH0NCnBlcGZvcm1fbm9ybSA8LSBwZXBmb3JtX25vcm0gJT4lDQogIG11dGF0ZShGZWF0dXJlVHlwZSA9ICJQZXB0aWRvZm9ybSAtIG5vcm1hbGlzZWQiKQ0KI3BlcGZvcm0gPC0gc2VsZWN0KC1jKCJwZXBmb3JtIikpDQpwZXBmb3JtX25vcm0kb3JpZ2luYWxSVU4gPC0gZm9yY2F0czo6ZmN0X2lub3JkZXIocGVwZm9ybV9ub3JtJG9yaWdpbmFsUlVOKQ0KDQojTm9ybWFsaXNlZCBQVE0gYWJ1bmRhbmNlDQpwdG1fZGYgPC0gYXNzYXkocGVbWyJwdG1SZWwiXV0pW2ksXSAlPiUgYXMuZGF0YS5mcmFtZSgpDQpjb2xuYW1lcyhwdG1fZGYpIDwtICJMb2dJbnRlbnNpdGllcyINCnB0bV9kZiA8LSBwdG1fZGYgJT4lDQogIG11dGF0ZShQcm90ZWluID0gaSwNCiAgICAgICAgIEZlYXR1cmVUeXBlID0gIlBUTSAtIG5vcm1hbGlzZWQiLA0KICAgICAgICAgR1JPVVAgPSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocHRtX2RmKSwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSkpICU+JQ0KICAgICAgICAgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnaW5hbFJVTiIpICU+JQ0KICAgICAgICAgYXJyYW5nZShHUk9VUCwgb3JpZ2luYWxSVU4pDQoNCg0KI1BUTSBlc3RpbWF0ZWQNClByb3RlaW4gPC0gcGFzdGUocmVwKGksIG5yb3cocHRtX2RmKSksICJlc3RpbWF0ZSIpDQpwdG1fZXN0aW1hdGUgPC0gdGliYmxlKFByb3RlaW4pDQpwdG1fZXN0aW1hdGUkb3JpZ2luYWxSVU4gPC0gcHRtX2RmJG9yaWdpbmFsUlVODQpwdG1fZXN0aW1hdGUkR1JPVVAgPC0gcHRtX2RmJEdST1VQDQpwdG1fZXN0aW1hdGUkRmVhdHVyZVR5cGUgPC0gIlBUTV9lc3RpbWF0ZWQiDQpwdG1fZXN0aW1hdGUkTG9nSW50ZW5zaXRpZXMgPC0gTkENCg0KZml4ZWZmZWN0cyA8LSByb3dEYXRhKHBlW1sicHRtUmVsIl1dKSRtc3Fyb2JNb2RlbHNbW2ldXSAlPiUgZ2V0Q29lZg0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRHUk9VUD09IkN0cmwiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ29tYm8iLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJDb21ibyIsIG5hbWVzKGZpeGVmZmVjdHMpKV1bMV0NCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJDQ0NQIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tncmVwbCgiQ0NDUCIsIG5hbWVzKGZpeGVmZmVjdHMpKV1bMV0NCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJVU1AzMF9PRSIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIlVTUDMwX09FIiwgbmFtZXMoZml4ZWZmZWN0cykpXVsxXQ0KcHRtX2VzdGltYXRlIDwtIHB0bV9lc3RpbWF0ZSAlPiUgYXJyYW5nZShHUk9VUCwgb3JpZ2luYWxSVU4pDQoNCnBsb3RfZGYgPC0gcmJpbmRsaXN0KGxpc3QocHJvdGVpbiwgcGVwZm9ybSwgcGVwZm9ybV9ub3JtLCBwdG1fZGYsIHB0bV9lc3RpbWF0ZSksIGZpbGwgPSBUUlVFKQ0KcGxvdF9kZiRvcmlnaW5hbFJVTiA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwbG90X2RmJG9yaWdpbmFsUlVOKQ0KcGxvdF9wb2ludHMgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKEZlYXR1cmVUeXBlICE9ICJQVE1fZXN0aW1hdGVkIikNCg0KI3Bsb3RfZGZbcGxvdF9kZiRGZWF0dXJlVHlwZSA9PSAnTW9kZWwnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gU3VtbWFyaXplZCINCiNwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ1BlcHRpZGUnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gRmVhdHVyZSINCg0KcDEgPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBQcm90ZWluLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9MikgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBwbG90X3BvaW50cywgYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBQcm90ZWluLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9IDUpICsNCiAgZ2VvbV92bGluZShkYXRhPWRhdGEuZnJhbWUoeCA9IGMoNC41LCA4LjUsIDEyLjUpKSwNCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdD1hcy5udW1lcmljKHgpKSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIlBlcHRpZG9mb3JtIC0gbm9ybWFsaXNlZCIgPSAiI0MzQzNDMyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb3RlaW4iID0gImRvZGdlcmJsdWUyIiwgIlBUTSAtIG5vcm1hbGlzZWQiID0gInNlYWdyZWVuMyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBUTV9lc3RpbWF0ZWQiID0gInBhbGV2aW9sZXRyZWQyIiwgIlBlcHRpZG9mb3JtIiA9ICJncmF5MzYiKSkgICsNCiAgI3NjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMikpICsNCiAgbGFicyh0aXRsZSA9IGksIHggPSAiQmlvUmVwbGljYXRlIiwgeSA9ICJMb2dJbnRlbnNpdHkiKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdD0xLCBzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSAgZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNSwgMC4wNSkpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMi41LCB5ID0gMzAsIGxhYmVsID0gIkNDQ1AiLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSA2LjUsIHkgPSAzMCwgbGFiZWwgPSAiQ29tYm8iLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxMC41LCB5ID0gMzAsIGxhYmVsID0gIkN0cmwiLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxNC41LCB5ID0gMzAsIGxhYmVsID0gIlVTUDMwIiwgc2l6ZSA9IDgpICsNCiAgeWxpbSgtNSwgMzApDQoNCnBsb3RzW1tpXV0gPC0gcDENCn0NCnBsb3RzDQpgYGANCg0KIyMjIENDQ1AgdnMgQ3RybA0KDQpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQojIyBQbG90IHB0bSdzIGZyb20gQ0NDUCB2cyBDdHJsDQpwdG1fbGlzdENDQ1AgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSkkZ3JvdXBDQ0NQICU+JSBmaWx0ZXIoYWRqUHZhbCA8PSAwLjA1KSAlPiUgcm93bmFtZXMoKQ0KcGxvdHMgPC0gYygpDQpmb3IgKGkgaW4gcHRtX2xpc3RDQ0NQKXsNCiAgcHJpbnQoaSkNCiAgcHJvdCA8LSBzdHJzcGxpdChpLCAiXyIpW1sxXV1bMV0NCg0KI1Byb3RlaW4gYWJ1bmRhbmNlDQpwcm90ZWluIDwtIGFzc2F5KHBlW1sicHJvdGVpblJhdyJdXSlbcHJvdCxdICU+JSBhcy5kYXRhLmZyYW1lKCkgDQpjb2xuYW1lcyhwcm90ZWluKSA8LSAiTG9nSW50ZW5zaXRpZXMiDQpwcm90ZWluIDwtIHByb3RlaW4gJT4lDQogIG11dGF0ZShQcm90ZWluID0gcHJvdCwNCiAgICAgICAgIEZlYXR1cmVUeXBlID0gIlByb3RlaW4iLA0KICAgICAgICAgR1JPVVAgPSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocHJvdGVpbiksICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pKSAlPiUNCiAgICAgICAgIHJvd25hbWVzX3RvX2NvbHVtbigib3JpZ2luYWxSVU4iKSAlPiUNCiAgICAgICAgIGFycmFuZ2UoR1JPVVAsIG9yaWdpbmFsUlVOKQ0KDQojUGVwdGlkb2Zvcm0gYWJ1bmRhbmNlDQpwZXBmb3JtcyA8LSByb3dEYXRhKHBlW1sicGVwdGlkb2Zvcm1SYXciXV0pICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIGZpbHRlcihwdG0gPT0gaSkgJT4lIHJvd25hbWVzDQpwZXBmb3JtIDwtIGFzc2F5KHBlW1sicGVwdGlkb2Zvcm1SYXciXV0pW3BlcGZvcm1zLF0gJT4lIGFzLmRhdGEuZnJhbWUoKQ0KaWYgKGxlbmd0aChwZXBmb3Jtcyk9PTApIHtuZXh0fQ0KaWYgKGxlbmd0aChwZXBmb3Jtcyk+MSl7DQogIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJQcm90ZWluIikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gY29sbmFtZXMocGVwZm9ybSksIG5hbWVzX3RvID0gIm9yaWdpbmFsUlVOIiwNCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIkxvZ0ludGVuc2l0aWVzIikgDQogIHBlcGZvcm0kR1JPVVAgPC0gc2FwcGx5KHN0cnNwbGl0KHBlcGZvcm0kb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pDQogIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgYXJyYW5nZShHUk9VUCwgb3JpZ2luYWxSVU4pDQp9IGVsc2Uge2NvbG5hbWVzKHBlcGZvcm0pIDwtICJMb2dJbnRlbnNpdGllcyINCiAgICAgICAgcGVwZm9ybSA8LSBwZXBmb3JtICU+JSByb3duYW1lc190b19jb2x1bW4oIm9yaWdpbmFsUlVOIikgDQogICAgICAgIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgbXV0YXRlKEdST1VQID0gDQogICAgICAgICAgICAgICAgICAgIHNhcHBseShzdHJzcGxpdChwZXBmb3JtJG9yaWdpbmFsUlVOLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKSwNCiAgICAgICAgICAgICAgICAgICAgUHJvdGVpbiA9IHBlcGZvcm1zWzFdKSAlPiUNCiAgICAgICAgICAgICAgICAgICBhcnJhbmdlKEdST1VQLCBvcmlnaW5hbFJVTikNCiAgICAgICAgfQ0KcGVwZm9ybSA8LSBwZXBmb3JtICU+JQ0KICBtdXRhdGUoRmVhdHVyZVR5cGUgPSAiUGVwdGlkb2Zvcm0iKQ0KI3BlcGZvcm0gPC0gc2VsZWN0KC1jKCJwZXBmb3JtIikpDQpwZXBmb3JtJG9yaWdpbmFsUlVOIDwtIGZvcmNhdHM6OmZjdF9pbm9yZGVyKHBlcGZvcm0kb3JpZ2luYWxSVU4pDQoNCiNQZXB0aWRvZm9ybSBhYnVuZGFuY2UgLSBub3JtYWxpc2VkDQpwZXBmb3JtcyA8LSByb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgZmlsdGVyKHB0bSA9PSBpKSAlPiUgcm93bmFtZXMNCnBlcGZvcm1fbm9ybSA8LSBhc3NheShwZVtbInBlcGZvcm1SZWwiXV0pW3BlcGZvcm1zLF0gJT4lIGFzLmRhdGEuZnJhbWUoKQ0KaWYgKGxlbmd0aChwZXBmb3Jtcyk+MSl7DQogIHBlcGZvcm1fbm9ybSA8LSBwZXBmb3JtX25vcm0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiUHJvdGVpbiIpICU+JSANCiAgICBwaXZvdF9sb25nZXIoY29scyA9IGNvbG5hbWVzKHBlcGZvcm1fbm9ybSksIG5hbWVzX3RvID0gIm9yaWdpbmFsUlVOIiwNCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIkxvZ0ludGVuc2l0aWVzIikgDQogIHBlcGZvcm1fbm9ybSRHUk9VUCA8LSBzYXBwbHkoc3Ryc3BsaXQocGVwZm9ybV9ub3JtJG9yaWdpbmFsUlVOLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKQ0KICBwZXBmb3JtX25vcm0gPC0gcGVwZm9ybV9ub3JtICU+JSBhcnJhbmdlKEdST1VQLCBvcmlnaW5hbFJVTikgJT4lDQogICAgbXV0YXRlKFByb3RlaW4gPSBwYXN0ZShQcm90ZWluLCJub3JtIikpDQp9IGVsc2Uge2NvbG5hbWVzKHBlcGZvcm1fbm9ybSkgPC0gIkxvZ0ludGVuc2l0aWVzIg0KICAgICAgICBwZXBmb3JtX25vcm0gPC0gcGVwZm9ybV9ub3JtICU+JSByb3duYW1lc190b19jb2x1bW4oIm9yaWdpbmFsUlVOIikgDQogICAgICAgIHBlcGZvcm1fbm9ybSA8LSBwZXBmb3JtX25vcm0gJT4lIG11dGF0ZShHUk9VUCA9IA0KICAgICAgICAgICAgICAgICAgICBzYXBwbHkoc3Ryc3BsaXQocGVwZm9ybV9ub3JtJG9yaWdpbmFsUlVOLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKSwNCiAgICAgICAgICAgICAgICAgICAgUHJvdGVpbiA9IHBhc3RlKHBlcGZvcm1zWzFdLCJub3JtIikpICU+JQ0KICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoR1JPVVAsIG9yaWdpbmFsUlVOKQ0KICAgICAgICB9DQpwZXBmb3JtX25vcm0gPC0gcGVwZm9ybV9ub3JtICU+JQ0KICBtdXRhdGUoRmVhdHVyZVR5cGUgPSAiUGVwdGlkb2Zvcm0gLSBub3JtYWxpc2VkIikNCiNwZXBmb3JtIDwtIHNlbGVjdCgtYygicGVwZm9ybSIpKQ0KcGVwZm9ybV9ub3JtJG9yaWdpbmFsUlVOIDwtIGZvcmNhdHM6OmZjdF9pbm9yZGVyKHBlcGZvcm1fbm9ybSRvcmlnaW5hbFJVTikNCg0KI05vcm1hbGlzZWQgUFRNIGFidW5kYW5jZQ0KcHRtX2RmIDwtIGFzc2F5KHBlW1sicHRtUmVsIl1dKVtpLF0gJT4lIGFzLmRhdGEuZnJhbWUoKQ0KY29sbmFtZXMocHRtX2RmKSA8LSAiTG9nSW50ZW5zaXRpZXMiDQpwdG1fZGYgPC0gcHRtX2RmICU+JQ0KICBtdXRhdGUoUHJvdGVpbiA9IGksDQogICAgICAgICBGZWF0dXJlVHlwZSA9ICJQVE0gLSBub3JtYWxpc2VkIiwNCiAgICAgICAgIEdST1VQID0gc2FwcGx5KHN0cnNwbGl0KHJvd25hbWVzKHB0bV9kZiksICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pKSAlPiUNCiAgICAgICAgIHJvd25hbWVzX3RvX2NvbHVtbigib3JpZ2luYWxSVU4iKSAlPiUNCiAgICAgICAgIGFycmFuZ2UoR1JPVVAsIG9yaWdpbmFsUlVOKQ0KDQoNCiNQVE0gZXN0aW1hdGVkDQpQcm90ZWluIDwtIHBhc3RlKHJlcChpLCBucm93KHB0bV9kZikpLCAiZXN0aW1hdGUiKQ0KcHRtX2VzdGltYXRlIDwtIHRpYmJsZShQcm90ZWluKQ0KcHRtX2VzdGltYXRlJG9yaWdpbmFsUlVOIDwtIHB0bV9kZiRvcmlnaW5hbFJVTg0KcHRtX2VzdGltYXRlJEdST1VQIDwtIHB0bV9kZiRHUk9VUA0KcHRtX2VzdGltYXRlJEZlYXR1cmVUeXBlIDwtICJQVE1fZXN0aW1hdGVkIg0KcHRtX2VzdGltYXRlJExvZ0ludGVuc2l0aWVzIDwtIE5BDQoNCmZpeGVmZmVjdHMgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSkkbXNxcm9iTW9kZWxzW1tpXV0gJT4lIGdldENvZWYNCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJDdHJsIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXQ0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRHUk9VUD09IkNvbWJvIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tncmVwbCgiQ29tYm8iLCBuYW1lcyhmaXhlZmZlY3RzKSldWzFdDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ0NDUCIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIkNDQ1AiLCBuYW1lcyhmaXhlZmZlY3RzKSldWzFdDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iVVNQMzBfT0UiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJVU1AzMF9PRSIsIG5hbWVzKGZpeGVmZmVjdHMpKV1bMV0NCnB0bV9lc3RpbWF0ZSA8LSBwdG1fZXN0aW1hdGUgJT4lIGFycmFuZ2UoR1JPVVAsIG9yaWdpbmFsUlVOKQ0KDQpwbG90X2RmIDwtIHJiaW5kbGlzdChsaXN0KHByb3RlaW4sIHBlcGZvcm0sIHBlcGZvcm1fbm9ybSwgcHRtX2RmLCBwdG1fZXN0aW1hdGUpLCBmaWxsID0gVFJVRSkNCnBsb3RfZGYkb3JpZ2luYWxSVU4gPC0gZm9yY2F0czo6ZmN0X2lub3JkZXIocGxvdF9kZiRvcmlnaW5hbFJVTikNCnBsb3RfcG9pbnRzIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihGZWF0dXJlVHlwZSAhPSAiUFRNX2VzdGltYXRlZCIpDQoNCiNwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ01vZGVsJ11bWydGZWF0dXJlVHlwZSddXSA8LSAiUFRNIFN1bW1hcml6ZWQiDQojcGxvdF9kZltwbG90X2RmJEZlYXR1cmVUeXBlID09ICdQZXB0aWRlJ11bWydGZWF0dXJlVHlwZSddXSA8LSAiUFRNIEZlYXR1cmUiDQoNCnAxIDwtIHBsb3RfZGYgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gUHJvdGVpbiwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gcGxvdF9wb2ludHMsIGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gUHJvdGVpbiwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPSA1KSArDQogIGdlb21fdmxpbmUoZGF0YT1kYXRhLmZyYW1lKHggPSBjKDQuNSwgOC41LCAxMi41KSksDQogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQ9YXMubnVtZXJpYyh4KSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJQZXB0aWRvZm9ybSAtIG5vcm1hbGlzZWQiID0gIiNDM0MzQzMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQcm90ZWluIiA9ICJkb2RnZXJibHVlMiIsICJQVE0gLSBub3JtYWxpc2VkIiA9ICJzZWFncmVlbjMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQVE1fZXN0aW1hdGVkIiA9ICJwYWxldmlvbGV0cmVkMiIsICJQZXB0aWRvZm9ybSIgPSAiZ3JheTM2IikpICArDQogICNzY2FsZV9zaXplX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDIpKSArDQogIGxhYnModGl0bGUgPSBpLCB4ID0gIkJpb1JlcGxpY2F0ZSIsIHkgPSAiTG9nSW50ZW5zaXR5IikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSwgc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gIGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDAuMDUpKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIuNSwgeSA9IDMwLCBsYWJlbCA9ICJDQ0NQIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNi41LCB5ID0gMzAsIGxhYmVsID0gIkNvbWJvIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTAuNSwgeSA9IDMwLCBsYWJlbCA9ICJDdHJsIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTQuNSwgeSA9IDMwLCBsYWJlbCA9ICJVU1AzMCIsIHNpemUgPSA4KSArDQogIHlsaW0oLTUsIDMwKQ0KDQpwbG90c1tbaV1dIDwtIHAxDQp9DQpwbG90cw0KYGBgDQoNCg0KYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEwfQ0KcGxvdHMgPC0gbGlzdCgpDQpmb3IgKGkgaW4gcHRtX2xpc3QyKXsNCnByb3RfID0gc3RyX3NwbGl0KGksICJfIilbWzFdXVsxXQ0Kc2l0ZV8gPSBzdHJfc3BsaXQoaSwgIl8iKVtbMV1dWzJdDQoNCnBlcGZvcm1fZGYgPC0gbG9uZ0Zvcm1hdChwZVssLCJwZXBmb3JtUmVsIl0sIHJvd3ZhcnMgPSBjKCJwcm90ZWluIiwgInB0bSIpLCBjb2x2YXJzID0gYygiZ3JvdXAiKSkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KcGVwZm9ybV9kZiA8LSBwZXBmb3JtX2RmICU+JSBmaWx0ZXIocHJvdGVpbiA9PSBwcm90XykNCnBlcGZvcm1fZGYgPC0gcGVwZm9ybV9kZiAlPiUgZmlsdGVyKGdyZXBsKHNpdGVfLCBwdG0sIGZpeGVkID0gVCkpDQpwZXBmb3JtX2RmJEZlYXR1cmVUeXBlIDwtICJQZXB0aWRlIg0KcGVwZm9ybV9kZiA8LSBwZXBmb3JtX2RmICU+JSBhcnJhbmdlKGdyb3VwLCByb3duYW1lKQ0KDQpwdG1fZGYgPC0gbG9uZ0Zvcm1hdChwZVssLCJwdG1SZWwiXSwgcm93dmFycyA9IGMoInByb3RlaW4iLCAicHRtIiksIGNvbHZhcnMgPSBjKCJncm91cCIpKSAlPiUgYXMuZGF0YS5mcmFtZSgpDQpwdG1fZGYgPC0gcHRtX2RmICU+JSBmaWx0ZXIocHRtID09IGkpDQpwdG1fZGYkRmVhdHVyZVR5cGUgPC0gIlBUTSINCnB0bV9kZiA8LSBwdG1fZGYgJT4lIGFycmFuZ2UoZ3JvdXAsIHJvd25hbWUpDQoNCnBsb3RfZGYgPC0gcmJpbmRsaXN0KGxpc3QocGVwZm9ybV9kZiwgcHRtX2RmKSwgZmlsbCA9IFRSVUUpDQoNCnBsb3RfZGZbcGxvdF9kZiRGZWF0dXJlVHlwZSA9PSAnUFRNJ11bWydGZWF0dXJlVHlwZSddXSA8LSAiUFRNIFN1bW1hcml6ZWQiDQpwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ1BlcHRpZGUnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gRmVhdHVyZSINCnBsb3RfZGYkcHJpbWFyeSA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwbG90X2RmJHByaW1hcnkpDQoNCnAxIDwtIHBsb3RfZGYgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gcHJpbWFyeSwgeSA9IHZhbHVlICwgZ3JvdXAgPSByb3duYW1lLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9MikgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gcHJpbWFyeSwgeSA9IHZhbHVlICwgZ3JvdXAgPSByb3duYW1lLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9IDUpICsNCiAgZ2VvbV92bGluZShkYXRhPWRhdGEuZnJhbWUoeCA9IGMoNC41LCA4LjUsIDEyLjUpKSwNCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdD1hcy5udW1lcmljKHgpKSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIiNDM0MzQzMiLCAiI0Q1NUUwMCIpKSArDQogICNzY2FsZV9zaXplX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDIpKSArDQogIGxhYnModGl0bGUgPSBpLCB4ID0gIkJpb1JlcGxpY2F0ZSIsIHkgPSAiQWJ1bmRhbmNlIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSwgc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gIGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDApKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIuNSwgeSA9IDYuNSwgbGFiZWwgPSAiQ3RybCIsIHNpemUgPSA2KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDYuNSwgeSA9IDYuNSwgbGFiZWwgPSAiQ0NDUCIsIHNpemUgPSA2KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEwLjUsIHkgPSA2LjUsIGxhYmVsID0gIkNvbWJvIiwgc2l6ZSA9IDYpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTQuNSwgeSA9IDYuNSwgbGFiZWwgPSAiVVNQMzAiLCBzaXplID0gNikgKw0KICB5bGltKC02LCA2LjUpDQoNCnBsb3RzW1tpXV0gPC0gcDENCn0NCnBsb3RzDQpgYGANCg0KIyMjIEZvciBNU3N0YXRzIHNpZ25pZmljYW50IHB0bXMNCg0KUGxvdHMgb2YgTVNzdGF0cyBmaXJzdCA0MCBzaWduaWZpY2FudCBQVE1zDQoNCg0KYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEwfQ0KIyMgUGxvdCBmb3VydHkgcHRtJ3MgZnJvbSBDb21ibyB2cyBDdHJsDQpwbG90cyA8LSBjKCkNCmZvciAoaSBpbiBwdG1fbGlzdDEpew0KICBwcmludChpKQ0KICBpZighaSAlaW4lIHJvd25hbWVzKGFzc2F5KHBlW1sicHRtUmVsIl1dKSkpew0KICAgIHByaW50KHBhc3RlKGksICJub3QgaW4gbXNxcm9iIikpDQogICAgbmV4dA0KICAgIH0NCiAgaWYoaSAlaW4lIHB0bV9saXN0Mil7cHJpbnQocGFzdGUoaSwgImFsc28gc2lnbmlmaWNhbnQgd2l0aCBtc3Fyb2IiKSl9DQogIHByb3QgPC0gc3Ryc3BsaXQoaSwgIl8iKVtbMV1dWzFdDQoNCiNQcm90ZWluIGFidW5kYW5jZQ0KcHJvdGVpbiA8LSBhc3NheShwZVtbInByb3RlaW5SYXciXV0pW3Byb3QsXSAlPiUgYXMuZGF0YS5mcmFtZSgpIA0KY29sbmFtZXMocHJvdGVpbikgPC0gIkxvZ0ludGVuc2l0aWVzIg0KcHJvdGVpbiA8LSBwcm90ZWluICU+JQ0KICBtdXRhdGUoUHJvdGVpbiA9IHByb3QsDQogICAgICAgICBGZWF0dXJlVHlwZSA9ICJQcm90ZWluIiwNCiAgICAgICAgIEdST1VQID0gc2FwcGx5KHN0cnNwbGl0KHJvd25hbWVzKHByb3RlaW4pLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKSkgJT4lDQogICAgICAgICByb3duYW1lc190b19jb2x1bW4oIm9yaWdpbmFsUlVOIikgJT4lDQogICAgICAgICBhcnJhbmdlKEdST1VQKQ0KDQojUGVwdGlkb2Zvcm0gYWJ1bmRhbmNlDQpwZXBmb3JtcyA8LSByb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgZmlsdGVyKHB0bSA9PSBpKSAlPiUgcm93bmFtZXMNCnBlcGZvcm0gPC0gYXNzYXkocGVbWyJwZXBmb3JtUmVsIl1dKVtwZXBmb3JtcyxdICU+JSBhcy5kYXRhLmZyYW1lKCkNCmlmKChucm93KHJvd0RhdGEocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgICAgICBmaWx0ZXIocHRtID09IGkpKT09MCkpe25leHR9DQppZiAobGVuZ3RoKHBlcGZvcm1zKT09MCl7DQogIHByaW50KHBhc3RlKGksICJub3QgaW4gbm9ybWFsaXNlZCBQVE0gZGF0YSIpKQ0KICBwZXBmb3JtcyA8LSByb3dEYXRhKHBlW1sicGVwdGlkb2Zvcm1SYXciXV0pICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIGZpbHRlcihwdG0gPT0gaSkgJT4lIHJvd25hbWVzDQogIHBlcGZvcm0gPC0gYXNzYXkocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSlbcGVwZm9ybXMsXSAlPiUgYXMuZGF0YS5mcmFtZSgpDQogIGlmIChsZW5ndGgocGVwZm9ybXMpPjEpew0KICBwZXBmb3JtIDwtIHBlcGZvcm0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiUHJvdGVpbiIpICU+JSANCiAgICBwaXZvdF9sb25nZXIoY29scyA9IGNvbG5hbWVzKHBlcGZvcm0pLCBuYW1lc190byA9ICJvcmlnaW5hbFJVTiIsDQogICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJMb2dJbnRlbnNpdGllcyIpIA0KICBwZXBmb3JtJEdST1VQIDwtIHNhcHBseShzdHJzcGxpdChwZXBmb3JtJG9yaWdpbmFsUlVOLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKQ0KICBwZXBmb3JtIDwtIHBlcGZvcm0gJT4lIGFycmFuZ2UocGVwZm9ybSwgR1JPVVApDQp9IGVsc2Uge2NvbG5hbWVzKHBlcGZvcm0pIDwtICJMb2dJbnRlbnNpdGllcyINCiAgICAgICAgcGVwZm9ybSA8LSBwZXBmb3JtICU+JSByb3duYW1lc190b19jb2x1bW4oIm9yaWdpbmFsUlVOIikgDQogICAgICAgIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgbXV0YXRlKEdST1VQID0gDQogICAgICAgICAgICAgICAgICAgIHNhcHBseShzdHJzcGxpdChwZXBmb3JtJG9yaWdpbmFsUlVOLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKSwNCiAgICAgICAgICAgICAgICAgICAgUHJvdGVpbiA9IHBlcGZvcm1zWzFdKSAlPiUNCiAgICAgICAgICAgICAgICAgICBhcnJhbmdlKEdST1VQKQ0KICAgICAgICB9DQogIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUNCiAgbXV0YXRlKEZlYXR1cmVUeXBlID0gInBlcGZvcm0gLSB1bm5vcm1hbGlzZWQiKQ0KICBwbG90X2RmIDwtIHJiaW5kbGlzdChsaXN0KHByb3RlaW4sIHBlcGZvcm0pLCBmaWxsID0gVFJVRSkNCiAgcDEgPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBQcm90ZWluLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9MikgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gUHJvdGVpbiwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPSA1KSArDQogIGdlb21fdmxpbmUoZGF0YT1kYXRhLmZyYW1lKHggPSBjKDQuNSwgOC41LCAxMi41KSksDQogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQ9YXMubnVtZXJpYyh4KSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJwZXBmb3JtIC0gdW5ub3JtYWxpc2VkIiA9ICJsaWdodGdvbGRlbnJvZCIsICJQcm90ZWluIiA9ICJwYWxlZ3JlZW4yIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUFRNIiA9ICJwYWxldmlvbGV0cmVkMiIsICJQVE1fZXN0aW1hdGVkIiA9ICJkZWVwcGluazQiKSkgKw0KICAjc2NhbGVfc2l6ZV9tYW51YWwodmFsdWVzID0gYygxLCAyKSkgKw0KICBsYWJzKHRpdGxlID0gcGFzdGUoaSwgIm5vIG5vcm1hbGlzYXRpb24gcG9zc2libGUiKSwgeCA9ICJCaW9SZXBsaWNhdGUiLCB5ID0gIkxvZ0ludGVuc2l0eSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0PTEsIHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9ICBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjA1KSkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLjUsIHkgPSAyNywgbGFiZWwgPSAiQ0NDUCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDYuNSwgeSA9IDI3LCBsYWJlbCA9ICJDb21ibyIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEwLjUsIHkgPSAyNywgbGFiZWwgPSAiQ3RybCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE0LjUsIHkgPSAyNywgbGFiZWwgPSAiVVNQMzAiLCBzaXplID0gOCkgKw0KICB5bGltKC03LCAyNykNCg0KcGxvdHNbW2ldXSA8LSBwMQ0KbmV4dA0KfQ0KaWYgKGxlbmd0aChwZXBmb3Jtcyk+MSl7DQogIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJQcm90ZWluIikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gY29sbmFtZXMocGVwZm9ybSksIG5hbWVzX3RvID0gIm9yaWdpbmFsUlVOIiwNCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIkxvZ0ludGVuc2l0aWVzIikgDQogIHBlcGZvcm0kR1JPVVAgPC0gc2FwcGx5KHN0cnNwbGl0KHBlcGZvcm0kb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pDQogIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgYXJyYW5nZShwZXBmb3JtLCBHUk9VUCkgJT4lDQogICAgbXV0YXRlKFByb3RlaW4gPSBwYXN0ZShQcm90ZWluLCAibm9ybWFsaXNlZCIpKQ0KfSBlbHNlIHtjb2xuYW1lcyhwZXBmb3JtKSA8LSAiTG9nSW50ZW5zaXRpZXMiDQogICAgICAgIHBlcGZvcm0gPC0gcGVwZm9ybSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnaW5hbFJVTiIpIA0KICAgICAgICBwZXBmb3JtIDwtIHBlcGZvcm0gJT4lIG11dGF0ZShHUk9VUCA9IA0KICAgICAgICAgICAgICAgICAgICBzYXBwbHkoc3Ryc3BsaXQocGVwZm9ybSRvcmlnaW5hbFJVTiwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSksDQogICAgICAgICAgICAgICAgICAgIFByb3RlaW4gPSBwYXN0ZShwZXBmb3Jtc1sxXSwgIm5vcm1hbGlzZWQiKSkgJT4lDQogICAgICAgICAgICAgICAgICAgYXJyYW5nZShHUk9VUCkNCiAgICAgICAgfQ0KcGVwZm9ybSA8LSBwZXBmb3JtICU+JQ0KICBtdXRhdGUoRmVhdHVyZVR5cGUgPSAiUGVwdGlkb2Zvcm0gLSBOb3JtYWxpc2VkIikNCg0KcGVwZm9ybSRvcmlnaW5hbFJVTiA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwZXBmb3JtJG9yaWdpbmFsUlVOKQ0KDQpwZXBmb3Jtc19yYXcgPC0gcm93RGF0YShwZVtbInBlcHRpZG9mb3JtUmF3Il1dKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgICBmaWx0ZXIocHRtID09IGkpICU+JSByb3duYW1lcw0KcGVwZm9ybV9yYXcgPC0gYXNzYXkocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSlbcGVwZm9ybXNfcmF3LF0gJT4lIGFzLmRhdGEuZnJhbWUoKQ0KaWYgKGxlbmd0aChwZXBmb3Jtc19yYXcpPjEpew0KICBwZXBmb3JtX3JhdyA8LSBwZXBmb3JtX3JhdyAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJQcm90ZWluIikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gY29sbmFtZXMocGVwZm9ybV9yYXcpLCBuYW1lc190byA9ICJvcmlnaW5hbFJVTiIsDQogICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJMb2dJbnRlbnNpdGllcyIpIA0KICBwZXBmb3JtX3JhdyRHUk9VUCA8LSBzYXBwbHkoc3Ryc3BsaXQocGVwZm9ybV9yYXckb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pDQogIHBlcGZvcm1fcmF3IDwtIHBlcGZvcm1fcmF3ICU+JSBhcnJhbmdlKHBlcGZvcm1fcmF3LCBHUk9VUCkNCn0gZWxzZSB7Y29sbmFtZXMocGVwZm9ybV9yYXcpIDwtICJMb2dJbnRlbnNpdGllcyINCiAgICAgICAgcGVwZm9ybV9yYXcgPC0gcGVwZm9ybV9yYXcgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigib3JpZ2luYWxSVU4iKSANCiAgICAgICAgcGVwZm9ybV9yYXcgPC0gcGVwZm9ybV9yYXcgJT4lIG11dGF0ZShHUk9VUCA9IA0KICAgICAgICAgICAgICAgICAgICBzYXBwbHkoc3Ryc3BsaXQocGVwZm9ybV9yYXckb3JpZ2luYWxSVU4sICItIiksIGZ1bmN0aW9uKHgpIHhbMV0pLA0KICAgICAgICAgICAgICAgICAgICBQcm90ZWluID0gcGVwZm9ybXNfcmF3WzFdKSAlPiUNCiAgICAgICAgICAgICAgICAgICBhcnJhbmdlKEdST1VQKQ0KICAgICAgICB9DQpwZXBmb3JtX3JhdyA8LSBwZXBmb3JtX3JhdyAlPiUNCiAgbXV0YXRlKEZlYXR1cmVUeXBlID0gIlBlcHRpZG9mb3JtIikNCg0KDQojTm9ybWFsaXNlZCBQVE0gYWJ1bmRhbmNlDQpwdG1fZGYgPC0gYXNzYXkocGVbWyJwdG1SZWwiXV0pW2ksXSAlPiUgYXMuZGF0YS5mcmFtZSgpDQpjb2xuYW1lcyhwdG1fZGYpIDwtICJMb2dJbnRlbnNpdGllcyINCnB0bV9kZiA8LSBwdG1fZGYgJT4lDQogIG11dGF0ZShQcm90ZWluID0gaSwNCiAgICAgICAgIEZlYXR1cmVUeXBlID0gIlBUTSAtIG5vcm1hbGlzZWQiLA0KICAgICAgICAgR1JPVVAgPSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocHRtX2RmKSwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSkpICU+JQ0KICAgICAgICAgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnaW5hbFJVTiIpICU+JQ0KICAgICAgICAgYXJyYW5nZShHUk9VUCkNCg0KDQojUFRNIGVzdGltYXRlZA0KUHJvdGVpbiA8LSBwYXN0ZShyZXAoaSwgbnJvdyhwdG1fZGYpKSwgImVzdGltYXRlIikNCnB0bV9lc3RpbWF0ZSA8LSB0aWJibGUoUHJvdGVpbikNCnB0bV9lc3RpbWF0ZSRvcmlnaW5hbFJVTiA8LSBwdG1fZGYkb3JpZ2luYWxSVU4NCnB0bV9lc3RpbWF0ZSRHUk9VUCA8LSBwdG1fZGYkR1JPVVANCnB0bV9lc3RpbWF0ZSRGZWF0dXJlVHlwZSA8LSAiUFRNX2VzdGltYXRlZCINCnB0bV9lc3RpbWF0ZSRMb2dJbnRlbnNpdGllcyA8LSBOQQ0KDQpmaXhlZmZlY3RzIDwtIHJvd0RhdGEocGVbWyJwdG1SZWwiXV0pJG1zcXJvYk1vZGVsc1tbaV1dICU+JSBnZXRDb2VmDQppZiAoISBhbGwoaXMuZmluaXRlKGZpeGVmZmVjdHMpKSl7cHJpbnQocGFzdGUoaSwgIm5vIHJlZml0dGluZyBwb3NzaWJsZSIpKQ0KICBuZXh0fQ0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRHUk9VUD09IkN0cmwiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ29tYm8iLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJDb21ibyIsIG5hbWVzKGZpeGVmZmVjdHMpKV1bMV0NCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJDQ0NQIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tncmVwbCgiQ0NDUCIsIG5hbWVzKGZpeGVmZmVjdHMpKV1bMV0NCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJVU1AzMF9PRSIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIlVTUDMwX09FIiwgbmFtZXMoZml4ZWZmZWN0cykpXVsxXQ0KDQoNCnBsb3RfZGYgPC0gcmJpbmRsaXN0KGxpc3QocHJvdGVpbiwgcGVwZm9ybSwgcHRtX2RmLCBwdG1fZXN0aW1hdGUsIHBlcGZvcm1fcmF3KSwgZmlsbCA9IFRSVUUpDQpwbG90X2RmJG9yaWdpbmFsUlVOIDwtIGFzLnZlY3RvcihwbG90X2RmJG9yaWdpbmFsUlVOKQ0KcGxvdF9kZiA8LSBwbG90X2RmICU+JSBhcnJhbmdlKEZlYXR1cmVUeXBlLCBvcmlnaW5hbFJVTikNCnBsb3RfZGYkb3JpZ2luYWxSVU4gPC0gZm9yY2F0czo6ZmN0X2lub3JkZXIocGxvdF9kZiRvcmlnaW5hbFJVTikNCnBsb3RfcG9pbnRzIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihGZWF0dXJlVHlwZSAhPSAiUFRNX2VzdGltYXRlZCIpDQoNCiNwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ01vZGVsJ11bWydGZWF0dXJlVHlwZSddXSA8LSAiUFRNIFN1bW1hcml6ZWQiDQojcGxvdF9kZltwbG90X2RmJEZlYXR1cmVUeXBlID09ICdQZXB0aWRlJ11bWydGZWF0dXJlVHlwZSddXSA8LSAiUFRNIEZlYXR1cmUiDQoNCnAxIDwtIHBsb3RfZGYgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gUHJvdGVpbiwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gcGxvdF9wb2ludHMsIGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gUHJvdGVpbiwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPSA1KSArDQogIGdlb21fdmxpbmUoZGF0YT1kYXRhLmZyYW1lKHggPSBjKDQuNSwgOC41LCAxMi41KSksDQogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQ9YXMubnVtZXJpYyh4KSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJQZXB0aWRvZm9ybSAtIG5vcm1hbGlzZWQiID0gIiNDM0MzQzMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQcm90ZWluIiA9ICJwYWxlZ3JlZW4yIiwgIlBUTSAtIG5vcm1hbGlzZWQiID0gImdvbGRlbnJvZDIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQVE1fZXN0aW1hdGVkIiA9ICJkZWVwcGluazQiLCAiUGVwdGlkb2Zvcm0iID0gImdyYXkzNiIpKSsNCiAgI3NjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMikpICsNCiAgbGFicyh0aXRsZSA9IGksIHggPSAiQmlvUmVwbGljYXRlIiwgeSA9ICJMb2dJbnRlbnNpdHkiKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdD0xLCBzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMS4zKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9ICBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjA1KSkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLjUsIHkgPSAzMCwgbGFiZWwgPSAiQ0NDUCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDYuNSwgeSA9IDMwLCBsYWJlbCA9ICJDb21ibyIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEwLjUsIHkgPSAzMCwgbGFiZWwgPSAiQ3RybCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE0LjUsIHkgPSAzMCwgbGFiZWwgPSAiVVNQMzAiLCBzaXplID0gOCkgKw0KICB5bGltKC01LCAzMCkNCg0KcGxvdHNbW2ldXSA8LSBwMQ0KfQ0KcGxvdHMNCmBgYA0KDQpgYGB7cn0NCmZvciAoaSBpbiBwdG1fbGlzdDEpew0KICBwcmludChpKQ0KICBpZighaSAlaW4lIHJvd25hbWVzKGFzc2F5KHBlW1sicHRtUmVsIl1dKSkpew0KICAgIHByaW50KHBhc3RlKGksICJub3QgaW4gbXNxcm9iIikpDQogICAgbmV4dA0KICAgIH0NCiAgcHJpbnQocm93RGF0YShwZVtbInB0bVJlbCJdXSkkZ3JvdXBDb21ib1tpLF0pDQogIH0NCmBgYA0KDQoNCiMjIE1zcXJvYiBmb3IgTVNzdGF0cyBzdW1tYXJ5DQoNCmVzdGltYXRlZCBwdG0gYWJ1bmRhbmNlIC0+IHJvd0RhdGEocGVNU3N0YXRzU3VtW1sicHRtTm9ybSJdXSkkbXNxcm9iTW9kZWxzJFAxODEyNF9LMDI5ICU+JSBnZXRDb2VmKCkNCnByb3RlaW4gYWJ1bmRhbmNlIC0+IHN1bW1hcml6ZWRfcHRtJFBST1RFSU4kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gaSkgJT4lIHB1bGwoTG9nSW50ZW5zaXRpZXMpDQpwdG0gYWJ1bmRhbmNlIC0+IGFzc2F5KHBlTVNzdGF0c1N1bVtbInB0bV1dKSBvZiBzdW1tYXJpemVkX3B0bSRQVE0kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gaSkgJT4lIHB1bGwoTG9nSW50ZW5zaXRpZXMpDQpub3JtYWxpc2VkIHB0bSBhYnVuZGFuY2UgLT4gYXNzYXkocGVNU3N0YXRzU3VtW1sicHRtTm9ybV1dKQ0KDQpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQojIyBQbG90IHNpZ25pZmljYW50IHB0bSdzIGZyb20gQ29tYm8gdnMgQ3RybA0KcHRtX2xpc3QzIDwtIHJvd0RhdGEocGVbWyJwdG1NU3N0YXRzUmVsIl1dKSRncm91cENvbWJvICU+JSBmaWx0ZXIoYWRqUHZhbCA8PSAwLjA1KSAlPiUgcm93bmFtZXMoKQ0KcGxvdHMgPC0gYygpDQpmb3IgKGkgaW4gcHRtX2xpc3QzKXsNCiAgcHJvdCA8LSBzdHJzcGxpdChpLCAiXyIpW1sxXV1bMV0NCg0KI1Byb3RlaW4gYWJ1bmRhbmNlDQpwcm90ZWluIDwtIHRpYmJsZShvcmlnaW5hbFJVTiwgR1JPVVApDQpwcm90ZWluJEZlYXR1cmVUeXBlIDwtICJQcm90ZWluIg0KcHJvdGVpbiRQcm90ZWluIDwtIHByb3QNCnRtcCA8LSBzdW1tYXJpemVkX3B0bSRQUk9URUlOJFByb3RlaW5MZXZlbERhdGEgJT4lIGZpbHRlcihQcm90ZWluID09IHByb3QpICU+JQ0KICBzZWxlY3QoYyhMb2dJbnRlbnNpdGllcywgb3JpZ2luYWxSVU4pKQ0KbWlzc2luZ19ydW5zIDwtIHNldGRpZmYob3JpZ2luYWxSVU4sIHRtcCRvcmlnaW5hbFJVTikNCnRtcDIgPC0gdGliYmxlKG9yaWdpbmFsUlVOID0gbWlzc2luZ19ydW5zLCBMb2dJbnRlbnNpdGllcyA9IE5BKQ0KdG1wMyA8LSByYmluZCh0bXAsIHRtcDIpICU+JSBhcnJhbmdlKG9yaWdpbmFsUlVOKSAlPiUgc2VsZWN0KExvZ0ludGVuc2l0aWVzKQ0KcHJvdGVpbiA8LSBjYmluZChwcm90ZWluLCB0bXAzKQ0KDQojUFRNIGFidW5kYW5jZQ0KcHRtX2RmIDwtIHRpYmJsZShvcmlnaW5hbFJVTiwgR1JPVVApDQpwdG1fZGYkRmVhdHVyZVR5cGUgPC0gIlBUTSINCnB0bV9kZiRQcm90ZWluIDwtIGkNCnRtcCA8LSBzdW1tYXJpemVkX3B0bSRQVE0kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gaSkgJT4lIA0KICBzZWxlY3QoYyhMb2dJbnRlbnNpdGllcywgb3JpZ2luYWxSVU4pKQ0KbWlzc2luZ19ydW5zIDwtIHNldGRpZmYob3JpZ2luYWxSVU4sIHRtcCRvcmlnaW5hbFJVTikNCnRtcDIgPC0gdGliYmxlKG9yaWdpbmFsUlVOID0gbWlzc2luZ19ydW5zLCBMb2dJbnRlbnNpdGllcyA9IE5BKQ0KdG1wMyA8LSByYmluZCh0bXAsIHRtcDIpICU+JSBhcnJhbmdlKG9yaWdpbmFsUlVOKSAlPiUgc2VsZWN0KExvZ0ludGVuc2l0aWVzKQ0KcHRtX2RmIDwtIGNiaW5kKHB0bV9kZiwgdG1wMykNCg0KDQojTm9ybWFsaXNlZCBQVE0gYWJ1bmRhbmNlDQpwdG1fZGZfbm9ybSA8LSBhc3NheShwZVtbInB0bU1Tc3RhdHNSZWwiXV0pW2ksXSAlPiUgYXMuZGF0YS5mcmFtZSgpDQpjb2xuYW1lcyhwdG1fZGZfbm9ybSkgPC0gIkxvZ0ludGVuc2l0aWVzIg0KcHRtX2RmX25vcm0gPC0gcHRtX2RmX25vcm0gJT4lDQogIG11dGF0ZShQcm90ZWluID0gaSwNCiAgICAgICAgIEZlYXR1cmVUeXBlID0gIlBUTSAtIG5vcm1hbGlzZWQiLA0KICAgICAgICAgR1JPVVAgPSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocHRtX2RmX25vcm0pLCAiLSIpLCBmdW5jdGlvbih4KSB4WzFdKSkgJT4lDQogICAgICAgICByb3duYW1lc190b19jb2x1bW4oIm9yaWdpbmFsUlVOIikgJT4lDQogICAgICAgICBhcnJhbmdlKEdST1VQKQ0KDQoNCiNQVE0gZXN0aW1hdGVkDQpQcm90ZWluIDwtIHJlcChpLCBucm93KHB0bV9kZikpDQpwdG1fZXN0aW1hdGUgPC0gdGliYmxlKFByb3RlaW4pDQpwdG1fZXN0aW1hdGUkb3JpZ2luYWxSVU4gPC0gcHRtX2RmJG9yaWdpbmFsUlVODQpwdG1fZXN0aW1hdGUkR1JPVVAgPC0gcHRtX2RmJEdST1VQDQpwdG1fZXN0aW1hdGUkRmVhdHVyZVR5cGUgPC0gIlBUTV9lc3RpbWF0ZWQiDQpwdG1fZXN0aW1hdGUkTG9nSW50ZW5zaXRpZXMgPC0gTkENCg0KZml4ZWZmZWN0cyA8LSByb3dEYXRhKHBlW1sicHRtTVNzdGF0c1JlbCJdXSkkbXNxcm9iTW9kZWxzW1tpXV0gJT4lIGdldENvZWYNCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJDdHJsIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXQ0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRHUk9VUD09IkNvbWJvIixdJExvZ0ludGVuc2l0aWVzIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tncmVwbCgiQ29tYm8iLCBuYW1lcyhmaXhlZmZlY3RzKSldWzFdDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ0NDUCIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIkNDQ1AiLCBuYW1lcyhmaXhlZmZlY3RzKSldWzFdDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iVVNQMzBfT0UiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW2dyZXBsKCJVU1AzMF9PRSIsIG5hbWVzKGZpeGVmZmVjdHMpKV1bMV0NCg0KDQpwbG90X2RmIDwtIHJiaW5kbGlzdChsaXN0KHByb3RlaW4sIHB0bV9kZl9ub3JtLCBwdG1fZGYsIHB0bV9lc3RpbWF0ZSksIGZpbGwgPSBUUlVFKQ0KcGxvdF9kZiA8LSBwbG90X2RmICU+JSBhcnJhbmdlKEZlYXR1cmVUeXBlKQ0KcGxvdF9kZiRvcmlnaW5hbFJVTiA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwbG90X2RmJG9yaWdpbmFsUlVOKQ0KcGxvdF9wb2ludHMgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKEZlYXR1cmVUeXBlICE9ICJQVE1fZXN0aW1hdGVkIikNCg0KI3Bsb3RfZGZbcGxvdF9kZiRGZWF0dXJlVHlwZSA9PSAnTW9kZWwnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gU3VtbWFyaXplZCINCiNwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ1BlcHRpZGUnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gRmVhdHVyZSINCg0KcDEgPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBGZWF0dXJlVHlwZSwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gcGxvdF9wb2ludHMsIGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gRmVhdHVyZVR5cGUsIGNvbG9yID0gRmVhdHVyZVR5cGUpLCBzaXplID0gNSkgKw0KICBnZW9tX3ZsaW5lKGRhdGE9ZGF0YS5mcmFtZSh4ID0gYyg0LjUsIDguNSwgMTIuNSkpLA0KICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0PWFzLm51bWVyaWMoeCkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJQVE0gLSBub3JtYWxpc2VkIiA9ICJsaWdodGdvbGRlbnJvZCIsICJQcm90ZWluIiA9ICJza3libHVlMyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBUTSIgPSAic2VhZ3JlZW4zIiwgIlBUTV9lc3RpbWF0ZWQiID0gInBhbGV2aW9sZXRyZWQyIikpICsNCiAgI3NjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMikpICsNCiAgbGFicyh0aXRsZSA9IGksIHggPSAiQmlvUmVwbGljYXRlIiwgeSA9ICJMb2dJbnRlbnNpdHkiKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdD0xLCBzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSAgZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNSwgMCkpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMi41LCB5ID0gMjcsIGxhYmVsID0gIkNDQ1AiLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSA2LjUsIHkgPSAyNywgbGFiZWwgPSAiQ29tYm8iLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxMC41LCB5ID0gMjcsIGxhYmVsID0gIkN0cmwiLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxNC41LCB5ID0gMjcsIGxhYmVsID0gIlVTUDMwIiwgc2l6ZSA9IDgpICsNCiAgeWxpbSgtNywgMjcpDQoNCnBsb3RzW1tpXV0gPC0gcDENCn0NCnBsb3RzDQpgYGANCg0KIyMjIEZvciBNU3N0YXRzIHNpZ25pZmljYW50IHB0bXMNCg0KYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEwfQ0KIyMgUGxvdCBmb3VydHkgcHRtJ3MgZnJvbSBDb21ibyB2cyBDdHJsDQpvcmlnaW5hbFJVTiA8LSBjKCJDQ0NQLUIxVDEiLCAiQ0NDUC1CMVQyIiwgIkNDQ1AtQjJUMSIsICJDQ0NQLUIyVDIiLCAiQ29tYm8tQjFUMSIsIA0KICAgICAgICAgICAgICAgICAiQ29tYm8tQjFUMiIsICJDb21iby1CMlQxIiwgIkNvbWJvLUIyVDIiLCAiQ3RybC1CMVQxIiwgIkN0cmwtQjFUMiIsICAgDQogICAgICAgICAgICAgICAgICJDdHJsLUIyVDEiLCAiQ3RybC1CMlQyIiwgIlVTUDMwX09FLUIxVDEiLCAiVVNQMzBfT0UtQjFUMiIsIA0KICAgICAgICAgICAgICAgICAiVVNQMzBfT0UtQjJUMSIsICJVU1AzMF9PRS1CMlQyIikNCkdST1VQIDwtIHNhcHBseShzdHJzcGxpdChvcmlnaW5hbFJVTiwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSkNCnBsb3RzIDwtIGMoKQ0KZm9yIChpIGluIHB0bV9saXN0MSl7DQogIGlmIChpICVpbiUgcHRtX2xpc3QzKXtwcmludChwYXN0ZShpLCAiYWxzbyBzaWduaWZpY2FudCBpbiBtc3Fyb2IiKSl9DQogIHByb3QgPC0gc3Ryc3BsaXQoaSwgIl8iKVtbMV1dWzFdDQoNCiNQcm90ZWluIGFidW5kYW5jZQ0KcHJvdGVpbiA8LSB0aWJibGUob3JpZ2luYWxSVU4sIEdST1VQKQ0KcHJvdGVpbiRGZWF0dXJlVHlwZSA8LSAiUHJvdGVpbiINCnByb3RlaW4kUHJvdGVpbiA8LSBwcm90DQp0bXAgPC0gc3VtbWFyaXplZF9wdG0kUFJPVEVJTiRQcm90ZWluTGV2ZWxEYXRhICU+JSBmaWx0ZXIoUHJvdGVpbiA9PSBwcm90KSAlPiUNCiAgc2VsZWN0KGMoTG9nSW50ZW5zaXRpZXMsIG9yaWdpbmFsUlVOKSkNCm1pc3NpbmdfcnVucyA8LSBzZXRkaWZmKG9yaWdpbmFsUlVOLCB0bXAkb3JpZ2luYWxSVU4pDQp0bXAyIDwtIHRpYmJsZShvcmlnaW5hbFJVTiA9IG1pc3NpbmdfcnVucywgTG9nSW50ZW5zaXRpZXMgPSBOQSkNCnRtcDMgPC0gcmJpbmQodG1wLCB0bXAyKSAlPiUgYXJyYW5nZShvcmlnaW5hbFJVTikgJT4lIHNlbGVjdChMb2dJbnRlbnNpdGllcykNCnByb3RlaW4gPC0gY2JpbmQocHJvdGVpbiwgdG1wMykNCg0KDQojUFRNIGFidW5kYW5jZQ0KcHRtX2RmIDwtIHRpYmJsZShvcmlnaW5hbFJVTiwgR1JPVVApDQpwdG1fZGYkRmVhdHVyZVR5cGUgPC0gIlBUTSINCnB0bV9kZiRQcm90ZWluIDwtIGkNCnRtcCA8LSBzdW1tYXJpemVkX3B0bSRQVE0kUHJvdGVpbkxldmVsRGF0YSAlPiUgZmlsdGVyKFByb3RlaW4gPT0gaSkgJT4lIA0KICBzZWxlY3QoYyhMb2dJbnRlbnNpdGllcywgb3JpZ2luYWxSVU4pKQ0KbWlzc2luZ19ydW5zIDwtIHNldGRpZmYob3JpZ2luYWxSVU4sIHRtcCRvcmlnaW5hbFJVTikNCnRtcDIgPC0gdGliYmxlKG9yaWdpbmFsUlVOID0gbWlzc2luZ19ydW5zLCBMb2dJbnRlbnNpdGllcyA9IE5BKQ0KdG1wMyA8LSByYmluZCh0bXAsIHRtcDIpICU+JSBhcnJhbmdlKG9yaWdpbmFsUlVOKSAlPiUgc2VsZWN0KExvZ0ludGVuc2l0aWVzKQ0KcHRtX2RmIDwtIGNiaW5kKHB0bV9kZiwgdG1wMykNCg0KI05vcm1hbGlzZWQgUFRNIGFidW5kYW5jZQ0KaWYgKCFpICVpbiUgcm93bmFtZXMoYXNzYXkocGVbWyJwdG1NU3N0YXRzUmVsIl1dKSkpew0KICBwcmludChwYXN0ZShpLCAibm90IGluIG5vcm1hbGlzZWQgUFRNIGRhdGEiKSkNCiAgcGxvdF9kZiA8LSByYmluZGxpc3QobGlzdChwcm90ZWluLCBwdG1fZGYpLCBmaWxsID0gVFJVRSkNCiAgcDEgPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBGZWF0dXJlVHlwZSwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IG9yaWdpbmFsUlVOLCB5ID0gTG9nSW50ZW5zaXRpZXMgLCBncm91cCA9IEZlYXR1cmVUeXBlLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9IDUpICsNCiAgZ2VvbV92bGluZShkYXRhPWRhdGEuZnJhbWUoeCA9IGMoNC41LCA4LjUsIDEyLjUpKSwNCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdD1hcy5udW1lcmljKHgpKSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIlBUTSAtIG5vcm1hbGlzZWQiID0gImxpZ2h0Z29sZGVucm9kIiwgIlByb3RlaW4iID0gInNreWJsdWUzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUFRNIiA9ICJzZWFncmVlbjMiLCAiUFRNX2VzdGltYXRlZCIgPSAicGFsZXZpb2xldHJlZDIiKSkgKw0KICAjc2NhbGVfc2l6ZV9tYW51YWwodmFsdWVzID0gYygxLCAyKSkgKw0KICBsYWJzKHRpdGxlID0gcGFzdGUoaSwgIm5vIG5vcm1hbGlzYXRpb24gcG9zc2libGUiKSwgeCA9ICJCaW9SZXBsaWNhdGUiLCB5ID0gIkxvZ0ludGVuc2l0eSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0PTEsIHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9ICBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwKSkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLjUsIHkgPSAyNywgbGFiZWwgPSAiQ0NDUCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDYuNSwgeSA9IDI3LCBsYWJlbCA9ICJDb21ibyIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEwLjUsIHkgPSAyNywgbGFiZWwgPSAiQ3RybCIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE0LjUsIHkgPSAyNywgbGFiZWwgPSAiVVNQMzAiLCBzaXplID0gOCkgKw0KICB5bGltKC03LCAyNykNCg0KcGxvdHNbW2ldXSA8LSBwMQ0KbmV4dA0KfQ0KcHRtX2RmX25vcm0gPC0gYXNzYXkocGVbWyJwdG1NU3N0YXRzUmVsIl1dKVtpLF0gJT4lIGFzLmRhdGEuZnJhbWUoKQ0KY29sbmFtZXMocHRtX2RmX25vcm0pIDwtICJMb2dJbnRlbnNpdGllcyINCnB0bV9kZl9ub3JtIDwtIHB0bV9kZl9ub3JtICU+JQ0KICBtdXRhdGUoUHJvdGVpbiA9IGksDQogICAgICAgICBGZWF0dXJlVHlwZSA9ICJQVE0gLSBub3JtYWxpc2VkIiwNCiAgICAgICAgIEdST1VQID0gc2FwcGx5KHN0cnNwbGl0KHJvd25hbWVzKHB0bV9kZl9ub3JtKSwgIi0iKSwgZnVuY3Rpb24oeCkgeFsxXSkpICU+JQ0KICAgICAgICAgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnaW5hbFJVTiIpICU+JQ0KICAgICAgICAgYXJyYW5nZShHUk9VUCkNCg0KDQojUFRNIGVzdGltYXRlZA0KUHJvdGVpbiA8LSByZXAoaSwgbnJvdyhwdG1fZGYpKQ0KcHRtX2VzdGltYXRlIDwtIHRpYmJsZShQcm90ZWluKQ0KcHRtX2VzdGltYXRlJG9yaWdpbmFsUlVOIDwtIHB0bV9kZiRvcmlnaW5hbFJVTg0KcHRtX2VzdGltYXRlJEdST1VQIDwtIHB0bV9kZiRHUk9VUA0KcHRtX2VzdGltYXRlJEZlYXR1cmVUeXBlIDwtICJQVE1fZXN0aW1hdGVkIg0KcHRtX2VzdGltYXRlJExvZ0ludGVuc2l0aWVzIDwtIE5BDQoNCmlmKHJvd0RhdGEocGVbWyJwdG1NU3N0YXRzUmVsIl1dKSRtc3Fyb2JNb2RlbHNbW2ldXSAlPiUgZ2V0Rml0TWV0aG9kKCkgPT0gImZpdEVycm9yIil7DQogICAgcHJpbnQocGFzdGUoaSwgInJlc3VsdGVkIGluIGEgZml0RXJyb3IiKSkNCiAgcGxvdF9kZiA8LSByYmluZGxpc3QobGlzdChwcm90ZWluLCBwdG1fZGYsIHB0bV9kZl9ub3JtKSwgZmlsbCA9IFRSVUUpDQogIHAxIDwtIHBsb3RfZGYgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gRmVhdHVyZVR5cGUsIGNvbG9yID0gRmVhdHVyZVR5cGUpLCBzaXplID0yKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBGZWF0dXJlVHlwZSwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPSA1KSArDQogIGdlb21fdmxpbmUoZGF0YT1kYXRhLmZyYW1lKHggPSBjKDQuNSwgOC41LCAxMi41KSksDQogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQ9YXMubnVtZXJpYyh4KSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJQVE0gLSBub3JtYWxpc2VkIiA9ICJsaWdodGdvbGRlbnJvZCIsICJQcm90ZWluIiA9ICJza3libHVlMyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBUTSIgPSAic2VhZ3JlZW4zIiwgIlBUTV9lc3RpbWF0ZWQiID0gInBhbGV2aW9sZXRyZWQyIikpICsNCiAgI3NjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMikpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlKGksICJmaXRFcnJvciIpLCB4ID0gIkJpb1JlcGxpY2F0ZSIsIHkgPSAiTG9nSW50ZW5zaXR5IikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSwgc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gIGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDApKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIuNSwgeSA9IDI3LCBsYWJlbCA9ICJDQ0NQIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNi41LCB5ID0gMjcsIGxhYmVsID0gIkNvbWJvIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTAuNSwgeSA9IDI3LCBsYWJlbCA9ICJDdHJsIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTQuNSwgeSA9IDI3LCBsYWJlbCA9ICJVU1AzMCIsIHNpemUgPSA4KSArDQogIHlsaW0oLTcsIDI3KQ0KDQpwbG90c1tbaV1dIDwtIHAxDQogIG5leHQNCn0NCmZpeGVmZmVjdHMgPC0gcm93RGF0YShwZVtbInB0bU1Tc3RhdHNSZWwiXV0pJG1zcXJvYk1vZGVsc1tbaV1dICU+JSBnZXRDb2VmDQp0cnkocHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRHUk9VUD09IkN0cmwiLF0kTG9nSW50ZW5zaXRpZXMgPC0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dKQ0KdHJ5KHB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJDb21ibyIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIkNvbWJvIiwgbmFtZXMoZml4ZWZmZWN0cykpXVsxXSkNCnRyeShwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJEdST1VQPT0iQ0NDUCIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIkNDQ1AiLCBuYW1lcyhmaXhlZmZlY3RzKSldWzFdKQ0KdHJ5KHB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkR1JPVVA9PSJVU1AzMF9PRSIsXSRMb2dJbnRlbnNpdGllcyA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbZ3JlcGwoIlVTUDMwX09FIiwgbmFtZXMoZml4ZWZmZWN0cykpXVsxXSkNCg0KDQpwbG90X2RmIDwtIHJiaW5kbGlzdChsaXN0KHByb3RlaW4sIHB0bV9kZl9ub3JtLCBwdG1fZGYsIHB0bV9lc3RpbWF0ZSksIGZpbGwgPSBUUlVFKQ0KcGxvdF9kZiA8LSBwbG90X2RmICU+JSBhcnJhbmdlKEZlYXR1cmVUeXBlKQ0KcGxvdF9kZiRvcmlnaW5hbFJVTiA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwbG90X2RmJG9yaWdpbmFsUlVOKQ0KcGxvdF9wb2ludHMgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKEZlYXR1cmVUeXBlICE9ICJQVE1fZXN0aW1hdGVkIikNCg0KI3Bsb3RfZGZbcGxvdF9kZiRGZWF0dXJlVHlwZSA9PSAnTW9kZWwnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gU3VtbWFyaXplZCINCiNwbG90X2RmW3Bsb3RfZGYkRmVhdHVyZVR5cGUgPT0gJ1BlcHRpZGUnXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gRmVhdHVyZSINCg0KcDEgPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBvcmlnaW5hbFJVTiwgeSA9IExvZ0ludGVuc2l0aWVzICwgZ3JvdXAgPSBGZWF0dXJlVHlwZSwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gcGxvdF9wb2ludHMsIGFlcyh4ID0gb3JpZ2luYWxSVU4sIHkgPSBMb2dJbnRlbnNpdGllcyAsIGdyb3VwID0gRmVhdHVyZVR5cGUsIGNvbG9yID0gRmVhdHVyZVR5cGUpLCBzaXplID0gNSkgKw0KICBnZW9tX3ZsaW5lKGRhdGE9ZGF0YS5mcmFtZSh4ID0gYyg0LjUsIDguNSwgMTIuNSkpLA0KICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0PWFzLm51bWVyaWMoeCkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiUFRNIC0gbm9ybWFsaXNlZCIgPSAibGlnaHRnb2xkZW5yb2QiLCAiUHJvdGVpbiIgPSAic2t5Ymx1ZTMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQVE0iID0gInNlYWdyZWVuMyIsICJQVE1fZXN0aW1hdGVkIiA9ICJwYWxldmlvbGV0cmVkMiIpKSArDQogICNzY2FsZV9zaXplX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDIpKSArDQogIGxhYnModGl0bGUgPSBpLCB4ID0gIkJpb1JlcGxpY2F0ZSIsIHkgPSAiTG9nSW50ZW5zaXR5IikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSwgc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMiksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gIGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDApKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIuNSwgeSA9IDMwLCBsYWJlbCA9ICJDQ0NQIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNi41LCB5ID0gMzAsIGxhYmVsID0gIkNvbWJvIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTAuNSwgeSA9IDMwLCBsYWJlbCA9ICJDdHJsIiwgc2l6ZSA9IDgpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTQuNSwgeSA9IDMwLCBsYWJlbCA9ICJVU1AzMCIsIHNpemUgPSA4KSArDQogIHlsaW0oLTEwLCAzMCkNCg0KcGxvdHNbW2ldXSA8LSBwMQ0KfQ0KcGxvdHMNCmBgYA0KDQpgYGB7cn0NCmZvciAoaSBpbiBwdG1fbGlzdDEpew0KICBwcmludChpKQ0KICBwcmludChyb3dEYXRhKHBlW1sicHRtTVNzdGF0c1JlbCJdXSkkZ3JvdXBDb21ib1tpLF0pDQogIH0NCmBgYA0K